/*
 * 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.geode.management.internal.cli.commands;

import static org.apache.geode.distributed.ConfigurationProperties.GROUPS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.io.File;
import java.io.Serializable;
import java.util.Properties;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import org.apache.geode.internal.ClassPathLoader;
import org.apache.geode.test.compiler.ClassBuilder;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.rules.GfshCommandRule;
import org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder;

/**
 * Unit tests for DeployCommand, UndeployCommand, ListDeployedCommand
 *
 * @since GemFire 7.0
 */
@SuppressWarnings("serial")
public class DeployWithGroupsDUnitTest implements Serializable {
  private static final String GROUP1 = "Group1";
  private static final String GROUP2 = "Group2";

  private final String class1 = "DeployCommandsDUnitA";
  private final String class2 = "DeployCommandsDUnitB";
  private final String class3 = "DeployCommandsDUnitC";
  private final String class4 = "DeployCommandsDUnitD";

  private final String jarName1 = "DeployCommandsDUnit1.jar";
  private final String jarName2 = "DeployCommandsDUnit2.jar";
  private final String jarName3 = "DeployCommandsDUnit3.jar";
  private final String jarName4 = "DeployCommandsDUnit4.jar";

  private File jar1;
  private File jar2;
  private File jar3;
  private File jar4;
  private File subdirWithJars3and4;

  private MemberVM locator;
  private MemberVM server1;
  private MemberVM server2;

  @Rule
  public SerializableTemporaryFolder temporaryFolder = new SerializableTemporaryFolder();

  @Rule
  public ClusterStartupRule lsRule = new ClusterStartupRule();

  @Rule
  public transient GfshCommandRule gfshConnector = new GfshCommandRule();

  @Before
  public void setup() throws Exception {
    ClassBuilder classBuilder = new ClassBuilder();
    File jarsDir = temporaryFolder.newFolder();
    jar1 = new File(jarsDir, jarName1);
    jar2 = new File(jarsDir, jarName2);

    subdirWithJars3and4 = new File(jarsDir, "subdir");
    subdirWithJars3and4.mkdirs();
    jar3 = new File(subdirWithJars3and4, jarName3);
    jar4 = new File(subdirWithJars3and4, jarName4);

    classBuilder.writeJarFromName(class1, jar1);
    classBuilder.writeJarFromName(class2, jar2);
    classBuilder.writeJarFromName(class3, jar3);
    classBuilder.writeJarFromName(class4, jar4);

    locator = lsRule.startLocatorVM(0);

    Properties props = new Properties();
    props.setProperty(GROUPS, GROUP1);
    server1 = lsRule.startServerVM(1, props, locator.getPort());

    props.setProperty(GROUPS, GROUP2);
    server2 = lsRule.startServerVM(2, props, locator.getPort());

    gfshConnector.connectAndVerify(locator);
  }

  @Test
  public void deployJarToOneGroup() throws Exception {
    // Deploy a jar to a single group
    gfshConnector.executeAndAssertThat("deploy --jar=" + jar2 + " --group=" + GROUP1)
        .statusIsSuccess();
    String resultString = gfshConnector.getGfshOutput();

    assertThat(resultString).contains(server1.getName());
    assertThat(resultString).doesNotContain(server2.getName());
    assertThat(resultString).contains(jarName2);

    server1.invoke(() -> assertThatCanLoad(jarName2, class2));
    server2.invoke(() -> assertThatCannotLoad(jarName2, class2));
  }

  @Test
  public void deployJarsInDirToOneGroup() throws Exception {
    // Deploy of multiple JARs to a single group
    gfshConnector
        .executeAndAssertThat(
            "deploy --group=" + GROUP1 + " --dir=" + subdirWithJars3and4.getCanonicalPath())
        .statusIsSuccess().containsOutput(server1.getName()).doesNotContainOutput(server2.getName())
        .containsOutput(jarName3).containsOutput(jarName4);

    server1.invoke(() -> {
      assertThatCanLoad(jarName3, class3);
      assertThatCanLoad(jarName4, class4);
    });
    server2.invoke(() -> {
      assertThatCannotLoad(jarName3, class3);
      assertThatCannotLoad(jarName4, class4);
    });

    // Undeploy of multiple jars by specifying group
    gfshConnector.executeAndAssertThat("undeploy --group=" + GROUP1).statusIsSuccess();
    server1.invoke(() -> {
      assertThatCannotLoad(jarName3, class3);
      assertThatCannotLoad(jarName4, class4);
    });
    server2.invoke(() -> {
      assertThatCannotLoad(jarName3, class3);
      assertThatCannotLoad(jarName4, class4);
    });
  }

  @Test
  public void deployMultipleJarsToOneGroup() throws Exception {
    // Deploy of multiple JARs to a single group
    gfshConnector
        .executeAndAssertThat("deploy --group=" + GROUP1 + " --jars=" + jar3.getAbsolutePath() + ","
            + jar4.getAbsolutePath())
        .statusIsSuccess().containsOutput(server1.getName()).doesNotContainOutput(server2.getName())
        .containsOutput(jarName3).containsOutput(jarName4);

    server1.invoke(() -> {
      assertThatCanLoad(jarName3, class3);
      assertThatCanLoad(jarName4, class4);
    });
    server2.invoke(() -> {
      assertThatCannotLoad(jarName3, class3);
      assertThatCannotLoad(jarName4, class4);
    });

    // Undeploy of multiple jars without specifying group
    gfshConnector.executeAndAssertThat("undeploy --jars=" + jarName3 + "," + jarName4)
        .statusIsSuccess()
        .hasTableSection("jars")
        .hasRowSize(4)
        .hasAnyRow().contains("server-1", "DeployCommandsDUnit3.jar")
        .hasAnyRow().contains("server-1", "DeployCommandsDUnit4.jar")
        .hasAnyRow()
        .contains("server-2", "DeployCommandsDUnit3.jar", "DeployCommandsDUnit3.jar not deployed")
        .hasAnyRow()
        .contains("server-2", "DeployCommandsDUnit4.jar", "DeployCommandsDUnit4.jar not deployed");
    server1.invoke(() -> {
      assertThatCannotLoad(jarName3, class3);
      assertThatCannotLoad(jarName4, class4);
    });
    server2.invoke(() -> {
      assertThatCannotLoad(jarName3, class3);
      assertThatCannotLoad(jarName4, class4);
    });
  }

  @Test
  public void deployJarToAllServers() throws Exception {
    // Deploy a jar to all servers
    gfshConnector.executeAndAssertThat("deploy --jar=" + jar1).statusIsSuccess();
    String resultString = gfshConnector.getGfshOutput();

    assertThat(resultString).contains(server1.getName());
    assertThat(resultString).contains(server2.getName());
    assertThat(resultString).contains(jarName1);

    server1.invoke(() -> assertThatCanLoad(jarName1, class1));
    server2.invoke(() -> assertThatCanLoad(jarName1, class1));

    // Undeploy of jar by specifying group
    gfshConnector.executeAndAssertThat("undeploy --group=" + GROUP1).statusIsSuccess();
    server1.invoke(() -> assertThatCannotLoad(jarName1, class1));
    server2.invoke(() -> assertThatCanLoad(jarName1, class1));
  }

  @Test
  public void deployJarToAllServersWithRestart() {
    // Deploy a jar to all servers
    gfshConnector.executeAndAssertThat("deploy --jar=" + jar1).statusIsSuccess();
    String resultString = gfshConnector.getGfshOutput();

    assertThat(resultString).contains(server1.getName());
    assertThat(resultString).contains(server2.getName());
    assertThat(resultString).contains(jarName1);

    server1.invoke(() -> assertThatCanLoad(jarName1, class1));
    server2.invoke(() -> assertThatCanLoad(jarName1, class1));

    server1.getVM().bounce();
    server2.getVM().bounce();

    // Restart the actual cache
    Properties props = new Properties();
    props.setProperty(GROUPS, GROUP1);
    server1 = lsRule.startServerVM(1, props, locator.getPort());

    props.setProperty(GROUPS, GROUP2);
    server2 = lsRule.startServerVM(2, props, locator.getPort());

    server1.invoke(() -> assertThatCanLoad(jarName1, class1));
    server2.invoke(() -> assertThatCanLoad(jarName1, class1));
  }

  @Test
  public void undeployJarFromAllServersWithRestart() throws Exception {
    // Deploy a jar to all servers
    gfshConnector.executeAndAssertThat("deploy --jar=" + jar1).statusIsSuccess();
    String resultString = gfshConnector.getGfshOutput();

    assertThat(resultString).contains(server1.getName());
    assertThat(resultString).contains(server2.getName());
    assertThat(resultString).contains(jarName1);

    server1.invoke(() -> assertThatCanLoad(jarName1, class1));
    server2.invoke(() -> assertThatCanLoad(jarName1, class1));

    gfshConnector.executeAndAssertThat("undeploy --jar=" + jar1.getName()).statusIsSuccess();
    server1.invoke(() -> assertThatCannotLoad(jarName1, class1));
    server2.invoke(() -> assertThatCannotLoad(jarName1, class1));

    server1.getVM().bounce();
    server2.getVM().bounce();

    // Restart the actual cache
    Properties props = new Properties();
    props.setProperty(GROUPS, GROUP1);
    server1 = lsRule.startServerVM(1, props, locator.getPort());

    props.setProperty(GROUPS, GROUP2);
    server2 = lsRule.startServerVM(2, props, locator.getPort());

    server1.invoke(() -> assertThatCannotLoad(jarName1, class1));
    server2.invoke(() -> assertThatCannotLoad(jarName1, class1));
  }

  @Test
  public void deployMultipleJarsToAllServers() throws Exception {
    gfshConnector.executeAndAssertThat("deploy --dir=" + subdirWithJars3and4.getCanonicalPath())
        .statusIsSuccess();

    server1.invoke(() -> {
      assertThatCanLoad(jarName3, class3);
      assertThatCanLoad(jarName4, class4);
    });
    server2.invoke(() -> {
      assertThatCanLoad(jarName3, class3);
      assertThatCanLoad(jarName4, class4);
    });

    gfshConnector.executeAndAssertThat("undeploy").statusIsSuccess();

    server1.invoke(() -> {
      assertThatCannotLoad(jarName3, class3);
      assertThatCannotLoad(jarName4, class4);
    });
    server2.invoke(() -> {
      assertThatCannotLoad(jarName3, class3);
      assertThatCannotLoad(jarName4, class4);
    });
  }

  @Test
  public void undeployOfMultipleJars() throws Exception {
    gfshConnector.executeAndAssertThat("deploy --dir=" + subdirWithJars3and4.getCanonicalPath())
        .statusIsSuccess();

    server1.invoke(() -> {
      assertThatCanLoad(jarName3, class3);
      assertThatCanLoad(jarName4, class4);
    });
    server2.invoke(() -> {
      assertThatCanLoad(jarName3, class3);
      assertThatCanLoad(jarName4, class4);
    });

    gfshConnector.executeAndAssertThat("undeploy --jar=" + jar3.getName() + "," + jar4.getName())
        .statusIsSuccess();
    server1.invoke(() -> {
      assertThatCannotLoad(jarName3, class3);
      assertThatCannotLoad(jarName4, class4);
    });
    server2.invoke(() -> {
      assertThatCannotLoad(jarName3, class3);
      assertThatCannotLoad(jarName4, class4);
    });
  }

  private void assertThatCanLoad(String jarName, String className) throws ClassNotFoundException {
    assertThat(ClassPathLoader.getLatest().getJarDeployer().getDeployedJar(jarName)).isNotNull();
    assertThat(ClassPathLoader.getLatest().forName(className)).isNotNull();
  }

  private void assertThatCannotLoad(String jarName, String className) {
    assertThat(ClassPathLoader.getLatest().getJarDeployer().getDeployedJar(jarName)).isNull();
    assertThatThrownBy(() -> ClassPathLoader.getLatest().forName(className))
        .isExactlyInstanceOf(ClassNotFoundException.class);
  }

  @Test
  public void testListDeployed() throws Exception {
    // Deploy a couple of JAR files which can be listed
    gfshConnector
        .executeAndAssertThat("deploy --group=" + GROUP1 + " --jar=" + jar1.getCanonicalPath())
        .statusIsSuccess();
    gfshConnector
        .executeAndAssertThat("deploy --group=" + GROUP2 + " --jar=" + jar2.getCanonicalPath())
        .statusIsSuccess();

    // List for all members
    gfshConnector.executeAndAssertThat("list deployed").statusIsSuccess();
    String resultString = gfshConnector.getGfshOutput();
    assertThat(resultString).contains(server1.getName());
    assertThat(resultString).contains(server2.getName());
    assertThat(resultString).contains(jarName1);
    assertThat(resultString).contains(jarName2);

    // List for members in Group1
    gfshConnector.executeAndAssertThat("list deployed --group=" + GROUP1).statusIsSuccess();
    resultString = gfshConnector.getGfshOutput();
    assertThat(resultString).contains(server1.getName());
    assertThat(resultString).doesNotContain(server2.getName());

    assertThat(resultString).contains(jarName1);
    assertThat(resultString).doesNotContain(jarName2);

    // List for members in Group2
    gfshConnector.executeAndAssertThat("list deployed --group=" + GROUP2).statusIsSuccess();
    resultString = gfshConnector.getGfshOutput();
    assertThat(resultString).doesNotContain(server1.getName());
    assertThat(resultString).contains(server2.getName());

    assertThat(resultString).doesNotContain(jarName1);
    assertThat(resultString).contains(jarName2);
  }
}
