/**
 * 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.falcon.regression.prism;

import org.apache.falcon.entity.v0.EntityType;
import org.apache.falcon.regression.core.bundle.Bundle;
import org.apache.falcon.regression.core.helpers.ColoHelper;
import org.apache.falcon.regression.core.util.AssertUtil;
import org.apache.falcon.regression.core.util.BundleUtil;
import org.apache.falcon.regression.core.util.OSUtil;
import org.apache.falcon.regression.core.util.Util;
import org.apache.falcon.regression.testHelper.BaseTestClass;
import org.apache.log4j.Logger;
import org.apache.oozie.client.Job;
import org.apache.oozie.client.OozieClient;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.io.IOException;
import java.lang.reflect.Method;

public class PrismProcessSuspendTest extends BaseTestClass {

    ColoHelper cluster1 = servers.get(0);
    ColoHelper cluster2 = servers.get(1);
    OozieClient cluster1OC = serverOC.get(0);
    OozieClient cluster2OC = serverOC.get(1);
    private boolean restartRequired;
    String aggregateWorkflowDir = baseHDFSDir + "/PrismProcessSuspendTest/aggregator";
    private static final Logger logger = Logger.getLogger(PrismProcessSuspendTest.class);

    @BeforeClass(alwaysRun = true)
    public void uploadWorkflow() throws Exception {
        uploadDirToClusters(aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
    }

    @BeforeMethod(alwaysRun = true)
    public void setUp(Method method) throws Exception {
        logger.info("test name: " + method.getName());
        restartRequired = false;
        Bundle bundle = BundleUtil.readLateDataBundle(baseAppHDFSDir,
            this.getClass().getSimpleName());
        for (int i = 0; i < 2; i++) {
            bundles[i] = new Bundle(bundle, servers.get(i));
            bundles[i].generateUniqueBundle();
            bundles[i].setProcessWorkflow(aggregateWorkflowDir);
        }

    }

    @AfterMethod(alwaysRun = true)
    public void tearDown() throws Exception {
        if (restartRequired) {
            Util.restartService(cluster1.getProcessHelper());
        }
        removeBundles();
    }


    @Test(groups = {"prism", "0.2", "distributed"})
    public void testSuspendSuspendedProcessOnBothColosWhen1ColoIsDown() throws Exception {
        restartRequired = true;

        //schedule using colohelpers
        bundles[0].submitAndScheduleProcessUsingColoHelper(cluster1);
        bundles[1].submitAndScheduleProcessUsingColoHelper(cluster2);


        //suspend using prismHelper
        AssertUtil.assertSucceeded(prism.getProcessHelper().suspend(bundles[0].getProcessData()));
        //verify
        AssertUtil.checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.SUSPENDED);
        AssertUtil.checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.RUNNING);

        Util.shutDownService(cluster1.getProcessHelper());

        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[0].getProcessData()));

        for (int i = 0; i < 2; i++) {
            //suspend on the other one
            AssertUtil.assertSucceeded(prism.getProcessHelper()
                .suspend(bundles[1].getProcessData()));
            AssertUtil
                .checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.SUSPENDED);
            AssertUtil
                .checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.SUSPENDED);
        }
    }


    @Test(groups = {"prism", "0.2", "distributed"})
    public void testSuspendScheduledProcessOnBothColos() throws Exception {
        //schedule using colohelpers
        bundles[0].submitAndScheduleProcessUsingColoHelper(cluster1);
        bundles[1].submitAndScheduleProcessUsingColoHelper(cluster2);

        //suspend using prismHelper
        AssertUtil.assertSucceeded(prism.getProcessHelper().suspend(bundles[0].getProcessData()));
        //verify
        AssertUtil.checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.SUSPENDED);
        AssertUtil.checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.RUNNING);

        //suspend on the other one
        AssertUtil.assertSucceeded(prism.getProcessHelper().suspend(bundles[0].getProcessData()));
        AssertUtil.checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.SUSPENDED);
        AssertUtil.checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.RUNNING);

        Assert.assertTrue(Util.parseResponse(prism.getProcessHelper()
            .getStatus(bundles[0].getProcessData())).getMessage()
            .contains("SUSPENDED"));
        Assert.assertTrue(Util.parseResponse(prism.getProcessHelper()
            .getStatus(bundles[1].getProcessData())).getMessage()
            .contains("RUNNING"));
    }

    @Test(groups = {"prism", "0.2", "distributed"})
    public void testSuspendDeletedProcessOnBothColos() throws Exception {
        //schedule using colohelpers
        bundles[0].submitAndScheduleProcessUsingColoHelper(cluster1);
        bundles[1].submitAndScheduleProcessUsingColoHelper(cluster2);

        //delete using coloHelpers
        AssertUtil.assertSucceeded(prism.getProcessHelper().delete(bundles[0].getProcessData()));


        //suspend using prismHelper
        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[0].getProcessData()));
        //verify
        AssertUtil.checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.KILLED);
        AssertUtil.checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.RUNNING);

        AssertUtil.assertSucceeded(prism.getProcessHelper().delete(bundles[1].getProcessData()));
        //suspend on the other one
        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[1].getProcessData()));
        AssertUtil.checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.KILLED);
        AssertUtil.checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.KILLED);
    }

    @Test(groups = {"prism", "0.2", "distributed"})
    public void testSuspendSuspendedProcessOnBothColos() throws Exception {
        //schedule using colohelpers
        bundles[0].submitAndScheduleProcessUsingColoHelper(cluster1);
        bundles[1].submitAndScheduleProcessUsingColoHelper(cluster2);


        for (int i = 0; i < 2; i++) {
            //suspend using prismHelper
            AssertUtil.assertSucceeded(prism.getProcessHelper()
                .suspend(bundles[0].getProcessData()));
            //verify
            AssertUtil
                .checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.SUSPENDED);
            AssertUtil.checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.RUNNING);
        }


        for (int i = 0; i < 2; i++) {
            //suspend on the other one
            AssertUtil.assertSucceeded(prism.getProcessHelper()
                .suspend(bundles[1].getProcessData()));
            AssertUtil
                .checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.SUSPENDED);
            AssertUtil
                .checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.SUSPENDED);
        }
    }

    @Test(groups = "embedded")
    public void testSuspendNonExistentProcessOnBothColos() throws Exception {
        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[0].getProcessData()));
        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[1].getProcessData()));

        AssertUtil.assertFailed(cluster1.getProcessHelper().suspend(bundles[0].getProcessData()));
        AssertUtil.assertFailed(cluster2.getProcessHelper().suspend(bundles[0].getProcessData()));
    }

    @Test(groups = "embedded")
    public void testSuspendSubmittedProcessOnBothColos() throws Exception {
        bundles[0].submitProcess(true);
        bundles[1].submitProcess(true);

        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[0].getProcessData()));
        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[1].getProcessData()));

        AssertUtil.assertFailed(cluster1.getProcessHelper().suspend(bundles[0].getProcessData()));
        AssertUtil.assertFailed(cluster2.getProcessHelper().suspend(bundles[1].getProcessData()));
    }

    @Test(groups = {"prism", "0.2", "distributed"})
    public void testSuspendScheduledProcessOnBothColosWhen1ColoIsDown() throws Exception {
        restartRequired = true;
        //schedule using colohelpers
        bundles[0].submitAndScheduleProcessUsingColoHelper(cluster1);
        bundles[1].submitAndScheduleProcessUsingColoHelper(cluster2);

        Util.shutDownService(cluster1.getProcessHelper());

        //suspend using prismHelper
        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[0].getProcessData()));
        //verify
        AssertUtil.checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.RUNNING);

        //suspend on the other one
        AssertUtil.assertSucceeded(prism.getProcessHelper().suspend(bundles[1].getProcessData()));
        AssertUtil.checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.SUSPENDED);
        AssertUtil.checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.RUNNING);
    }

    @Test(groups = {"prism", "0.2", "distributed"})
    public void testSuspendDeletedProcessOnBothColosWhen1ColoIsDown() throws Exception {
        restartRequired = true;         //schedule using colohelpers
        bundles[0].submitAndScheduleProcessUsingColoHelper(cluster1);
        bundles[1].submitAndScheduleProcessUsingColoHelper(cluster2);

        //delete using coloHelpers
        AssertUtil.assertSucceeded(prism.getProcessHelper().delete(bundles[0].getProcessData()));

        Util.shutDownService(cluster1.getProcessHelper());

        //suspend using prismHelper
        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[0].getProcessData()));
        //verify
        AssertUtil.checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.KILLED);
        AssertUtil.checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.RUNNING);

        AssertUtil.assertSucceeded(prism.getProcessHelper().delete(bundles[1].getProcessData()));
        //suspend on the other one
        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[1].getProcessData()));
        AssertUtil.checkStatus(cluster1OC, EntityType.PROCESS, bundles[0], Job.Status.KILLED);
        AssertUtil.checkStatus(cluster2OC, EntityType.PROCESS, bundles[1], Job.Status.KILLED);
    }


    @Test(groups = "distributed")
    public void testSuspendNonExistentProcessOnBothColosWhen1ColoIsDown() throws Exception {
        restartRequired = true;
        Util.shutDownService(cluster1.getProcessHelper());

        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[1].getProcessData()));
        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[0].getProcessData()));

        AssertUtil.assertFailed(cluster2.getProcessHelper().suspend(bundles[0].getProcessData()));
    }

    @Test(groups = "distributed")
    public void testSuspendSubmittedFeedOnBothColosWhen1ColoIsDown() throws Exception {
        restartRequired = true;
        bundles[0].submitProcess(true);
        bundles[1].submitProcess(true);

        Util.shutDownService(cluster1.getProcessHelper());

        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[0].getProcessData()));
        AssertUtil.assertFailed(prism.getProcessHelper().suspend(bundles[1].getProcessData()));
        AssertUtil.assertFailed(cluster2.getProcessHelper().suspend(bundles[1].getProcessData()));
    }

    @AfterClass(alwaysRun = true)
    public void tearDownClass() throws IOException {
        cleanTestDirs();
    }
}
