You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2017/08/19 00:10:11 UTC

[16/51] [abbrv] geode git commit: GEODE-3383: Refactor deploy tests

GEODE-3383: Refactor deploy tests


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/c5dd26b7
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/c5dd26b7
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/c5dd26b7

Branch: refs/heads/feature/GEODE-1279
Commit: c5dd26b7f7317c93666583b405006e1bb7c9255e
Parents: e07b5c1
Author: Jared Stewart <js...@pivotal.io>
Authored: Tue Aug 8 10:32:32 2017 -0700
Committer: Jared Stewart <js...@pivotal.io>
Committed: Tue Aug 15 15:42:11 2017 -0700

----------------------------------------------------------------------
 .../ClassPathLoaderIntegrationTest.java         | 171 ++++++++
 .../geode/internal/DeployedJarJUnitTest.java    | 400 ++-----------------
 .../geode/internal/JarDeployerDeadlockTest.java | 131 ++++++
 .../geode/management/DeployJarTestSuite.java    |   4 +-
 .../cli/commands/DeployCommandsDUnitTest.java   | 303 --------------
 .../cli/commands/DeployWithGroupsDUnitTest.java | 303 ++++++++++++++
 .../cli/commands/CommandOverHttpDUnitTest.java  |   2 +-
 7 files changed, 636 insertions(+), 678 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/c5dd26b7/geode-core/src/test/java/org/apache/geode/internal/ClassPathLoaderIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/ClassPathLoaderIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/ClassPathLoaderIntegrationTest.java
index 34d8a23..2fdc085 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/ClassPathLoaderIntegrationTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/ClassPathLoaderIntegrationTest.java
@@ -27,9 +27,11 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.Enumeration;
 import java.util.List;
+import java.util.Random;
 import java.util.Vector;
 
 import org.apache.bcel.Constants;
@@ -44,10 +46,14 @@ import org.junit.experimental.categories.Category;
 import org.junit.rules.TemporaryFolder;
 
 import org.apache.geode.cache.execute.Execution;
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.cache.execute.FunctionContext;
 import org.apache.geode.cache.execute.FunctionService;
 import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.cache.execute.ResultSender;
 import org.apache.geode.distributed.DistributedSystem;
 import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.internal.cache.execute.FunctionContextImpl;
 import org.apache.geode.test.dunit.rules.ServerStarterRule;
 import org.apache.geode.test.junit.categories.IntegrationTest;
 import org.apache.geode.test.junit.rules.RestoreTCCLRule;
@@ -64,6 +70,7 @@ public class ClassPathLoaderIntegrationTest {
 
   private File tempFile;
   private File tempFile2;
+  private ClassBuilder classBuilder = new ClassBuilder();
 
   @Rule
   public RestoreTCCLRule restoreTCCLRule = new RestoreTCCLRule();
@@ -452,6 +459,145 @@ public class ClassPathLoaderIntegrationTest {
     }
   }
 
+  @Test
+  public void testDeclarableFunctionsWithNoCacheXml() throws Exception {
+    final String jarName = "JarClassLoaderJUnitNoXml.jar";
+
+    // Add a Declarable Function without parameters for the class to the Classpath
+    String functionString =
+        "import java.util.Properties;" + "import org.apache.geode.cache.Declarable;"
+            + "import org.apache.geode.cache.execute.Function;"
+            + "import org.apache.geode.cache.execute.FunctionContext;"
+            + "public class JarClassLoaderJUnitFunctionNoXml implements Function, Declarable {"
+            + "public String getId() {return \"JarClassLoaderJUnitFunctionNoXml\";}"
+            + "public void init(Properties props) {}"
+            + "public void execute(FunctionContext context) {context.getResultSender().lastResult(\"NOPARMSv1\");}"
+            + "public boolean hasResult() {return true;}"
+            + "public boolean optimizeForWrite() {return false;}"
+            + "public boolean isHA() {return false;}}";
+
+    byte[] jarBytes = this.classBuilder
+        .createJarFromClassContent("JarClassLoaderJUnitFunctionNoXml", functionString);
+
+    ClassPathLoader.getLatest().getJarDeployer().deploy(jarName, jarBytes);
+
+    ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunctionNoXml");
+
+    // Check to see if the function without parameters executes correctly
+    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunctionNoXml");
+    assertThat(function).isNotNull();
+    TestResultSender resultSender = new TestResultSender();
+    function.execute(new FunctionContextImpl(null, function.getId(), null, resultSender));
+    assertThat((String) resultSender.getResults()).isEqualTo("NOPARMSv1");
+  }
+
+  @Test
+  public void testDependencyBetweenJars() throws Exception {
+    final File parentJarFile = temporaryFolder.newFile("JarClassLoaderJUnitParent.jar");
+    final File usesJarFile = temporaryFolder.newFile("JarClassLoaderJUnitUses.jar");
+
+    // Write out a JAR files.
+    StringBuffer stringBuffer = new StringBuffer();
+    stringBuffer.append("package jcljunit.parent;");
+    stringBuffer.append("public class JarClassLoaderJUnitParent {");
+    stringBuffer.append("public String getValueParent() {");
+    stringBuffer.append("return \"PARENT\";}}");
+
+    byte[] jarBytes = this.classBuilder.createJarFromClassContent(
+        "jcljunit/parent/JarClassLoaderJUnitParent", stringBuffer.toString());
+    writeJarBytesToFile(parentJarFile, jarBytes);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitParent.jar", jarBytes);
+
+    stringBuffer = new StringBuffer();
+    stringBuffer.append("package jcljunit.uses;");
+    stringBuffer.append("public class JarClassLoaderJUnitUses {");
+    stringBuffer.append("public String getValueUses() {");
+    stringBuffer.append("return \"USES\";}}");
+
+    jarBytes = this.classBuilder.createJarFromClassContent("jcljunit/uses/JarClassLoaderJUnitUses",
+        stringBuffer.toString());
+    writeJarBytesToFile(usesJarFile, jarBytes);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitUses.jar", jarBytes);
+
+    stringBuffer = new StringBuffer();
+    stringBuffer.append("package jcljunit.function;");
+    stringBuffer.append("import jcljunit.parent.JarClassLoaderJUnitParent;");
+    stringBuffer.append("import jcljunit.uses.JarClassLoaderJUnitUses;");
+    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
+    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
+    stringBuffer.append(
+        "public class JarClassLoaderJUnitFunction  extends JarClassLoaderJUnitParent implements Function {");
+    stringBuffer.append("private JarClassLoaderJUnitUses uses = new JarClassLoaderJUnitUses();");
+    stringBuffer.append("public boolean hasResult() {return true;}");
+    stringBuffer.append(
+        "public void execute(FunctionContext context) {context.getResultSender().lastResult(getValueParent() + \":\" + uses.getValueUses());}");
+    stringBuffer.append("public String getId() {return \"JarClassLoaderJUnitFunction\";}");
+    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
+    stringBuffer.append("public boolean isHA() {return false;}}");
+
+    ClassBuilder functionClassBuilder = new ClassBuilder();
+    functionClassBuilder.addToClassPath(parentJarFile.getAbsolutePath());
+    functionClassBuilder.addToClassPath(usesJarFile.getAbsolutePath());
+    jarBytes = functionClassBuilder.createJarFromClassContent(
+        "jcljunit/function/JarClassLoaderJUnitFunction", stringBuffer.toString());
+
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitFunction.jar",
+        jarBytes);
+
+    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
+    assertThat(function).isNotNull();
+    TestResultSender resultSender = new TestResultSender();
+    FunctionContext functionContext =
+        new FunctionContextImpl(null, function.getId(), null, resultSender);
+    function.execute(functionContext);
+    assertThat((String) resultSender.getResults()).isEqualTo("PARENT:USES");
+  }
+
+  @Test
+  public void testFindResource() throws IOException, ClassNotFoundException {
+    final String fileName = "file.txt";
+    final String fileContent = "FILE CONTENT";
+
+    byte[] jarBytes = this.classBuilder.createJarFromFileContent(fileName, fileContent);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitResource.jar",
+        jarBytes);
+
+    InputStream inputStream = ClassPathLoader.getLatest().getResourceAsStream(fileName);
+    assertThat(inputStream).isNotNull();
+
+    final byte[] fileBytes = new byte[fileContent.length()];
+    inputStream.read(fileBytes);
+    inputStream.close();
+    assertThat(fileContent).isEqualTo(new String(fileBytes));
+  }
+
+
+  @Test
+  public void testUpdateClassInJar() throws Exception {
+    // First use of the JAR file
+    byte[] jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitTestClass",
+        "public class JarClassLoaderJUnitTestClass { public Integer getValue5() { return new Integer(5); } }");
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitUpdate.jar", jarBytes);
+
+    Class<?> clazz = ClassPathLoader.getLatest().forName("JarClassLoaderJUnitTestClass");
+    Object object = clazz.newInstance();
+    Method getValue5Method = clazz.getMethod("getValue5");
+    Integer value = (Integer) getValue5Method.invoke(object);
+    assertThat(value).isEqualTo(5);
+
+    // Now create an updated JAR file and make sure that the method from the new
+    // class is available.
+    jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitTestClass",
+        "public class JarClassLoaderJUnitTestClass { public Integer getValue10() { return new Integer(10); } }");
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitUpdate.jar", jarBytes);
+
+    clazz = ClassPathLoader.getLatest().forName("JarClassLoaderJUnitTestClass");
+    object = clazz.newInstance();
+    Method getValue10Method = clazz.getMethod("getValue10");
+    value = (Integer) getValue10Method.invoke(object);
+    assertThat(value).isEqualTo(10);
+  }
+
   private void writeJarBytesToFile(File jarFile, byte[] jarBytes) throws IOException {
     final OutputStream outStream = new FileOutputStream(jarFile);
     outStream.write(jarBytes);
@@ -538,4 +684,29 @@ public class ClassPathLoaderIntegrationTest {
     return new ClassBuilder().createJarFromClassContent("integration/parent/" + className,
         stringBuilder);
   }
+
+  private static class TestResultSender implements ResultSender<Object> {
+    private Object result;
+
+    public TestResultSender() {}
+
+    protected Object getResults() {
+      return this.result;
+    }
+
+    @Override
+    public void lastResult(final Object lastResult) {
+      this.result = lastResult;
+    }
+
+    @Override
+    public void sendResult(final Object oneResult) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendException(final Throwable t) {
+      throw new UnsupportedOperationException();
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/c5dd26b7/geode-core/src/test/java/org/apache/geode/internal/DeployedJarJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/DeployedJarJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/DeployedJarJUnitTest.java
index 178dbae..853696a 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/DeployedJarJUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/DeployedJarJUnitTest.java
@@ -18,411 +18,67 @@ package org.apache.geode.internal;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import org.apache.geode.cache.execute.Function;
-import org.apache.geode.cache.execute.FunctionContext;
-import org.apache.geode.cache.execute.FunctionService;
-import org.apache.geode.cache.execute.ResultSender;
-import org.apache.geode.internal.cache.execute.FunctionContextImpl;
+import org.apache.geode.test.compiler.JarBuilder;
 import org.apache.geode.test.junit.categories.IntegrationTest;
-import org.awaitility.Awaitility;
-import org.junit.After;
+
+import org.apache.commons.io.FileUtils;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.contrib.java.lang.system.RestoreSystemProperties;
 import org.junit.experimental.categories.Category;
 import org.junit.rules.TemporaryFolder;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-import java.lang.reflect.Method;
-import java.util.Random;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
 
 @Category(IntegrationTest.class)
 public class DeployedJarJUnitTest {
+  private static final String JAR_NAME = "test.jar";
   @Rule
   public TemporaryFolder temporaryFolder = new TemporaryFolder();
 
-  @Rule
-  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
-
-  private ClassBuilder classBuilder;
+  private JarBuilder jarBuilder;
+  private File jarFile;
+  private byte[] expectedJarBytes;
 
   @Before
   public void setup() throws Exception {
-    File workingDir = temporaryFolder.newFolder();
-    ClassPathLoader.setLatestToDefault(workingDir);
-    classBuilder = new ClassBuilder();
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    for (String functionName : FunctionService.getRegisteredFunctions().keySet()) {
-      FunctionService.unregisterFunction(functionName);
-    }
-
-    ClassPathLoader.setLatestToDefault();
+    jarBuilder = new JarBuilder();
+    jarFile = new File(temporaryFolder.getRoot(), JAR_NAME);
+    jarBuilder.buildJarFromClassNames(jarFile, "ExpectedClass");
+    expectedJarBytes = FileUtils.readFileToByteArray(jarFile);
   }
 
   @Test
-  public void testIsValidJarContent() throws IOException {
-    assertThat(
-        DeployedJar.hasValidJarContent(this.classBuilder.createJarFromName("JarClassLoaderJUnitA")))
-            .isTrue();
+  public void validJarContentDoesNotThrow() throws Exception {
+    new DeployedJar(jarFile, JAR_NAME, expectedJarBytes);
   }
 
   @Test
-  public void testIsInvalidJarContent() {
-    assertThat(DeployedJar.hasValidJarContent("INVALID JAR CONTENT".getBytes())).isFalse();
-  }
-
-  @Test
-  public void testClassOnClasspath() throws Exception {
-    // Deploy the first JAR file and make sure the class is on the Classpath
-    byte[] jarBytes =
-        this.classBuilder.createJarFromClassContent("com/jcljunit/JarClassLoaderJUnitA",
-            "package com.jcljunit; public class JarClassLoaderJUnitA {}");
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnit.jar", jarBytes);
-
-    ClassPathLoader.getLatest().forName("com.jcljunit.JarClassLoaderJUnitA");
+  public void unexpectedContentThrowsException() throws Exception {
+    givenUnexpectedJarFileContents();
 
-    // Update the JAR file and make sure the first class is no longer on the Classpath
-    // and the second one is.
-    jarBytes = this.classBuilder.createJarFromClassContent("com/jcljunit/JarClassLoaderJUnitB",
-        "package com.jcljunit; public class JarClassLoaderJUnitB {}");
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnit.jar", jarBytes);
-
-    ClassPathLoader.getLatest().forName("com.jcljunit.JarClassLoaderJUnitB");
-    assertThatThrownBy(
-        () -> ClassPathLoader.getLatest().forName("com.jcljunit.JarClassLoaderJUnitA"))
-            .isInstanceOf(ClassNotFoundException.class);
+    assertThatThrownBy(() -> new DeployedJar(jarFile, JAR_NAME, expectedJarBytes))
+        .isInstanceOf(IllegalStateException.class);
   }
 
   @Test
-  public void testFailingCompilation() throws Exception {
-    String functionString = "import org.apache.geode.cache.Declarable;"
-        + "import org.apache.geode.cache.execute.Function;"
-        + "import org.apache.geode.cache.execute.FunctionContext;"
-        + "public class JarClassLoaderJUnitFunction implements Function {}";
+  public void invalidContentThrowsException() throws Exception {
+    byte[] invalidJarBytes = givenInvalidJarBytes();
 
-    assertThatThrownBy(() -> this.classBuilder
-        .createJarFromClassContent("JarClassLoaderJUnitFunction", functionString)).isNotNull();
+    assertThatThrownBy(() -> new DeployedJar(jarFile, JAR_NAME, invalidJarBytes))
+        .isInstanceOf(IllegalArgumentException.class);
   }
 
-  @Test
-  public void testFunctions() throws Exception {
-    // Test creating a JAR file with a function
-    String functionString =
-        "import java.util.Properties;" + "import org.apache.geode.cache.Declarable;"
-            + "import org.apache.geode.cache.execute.Function;"
-            + "import org.apache.geode.cache.execute.FunctionContext;"
-            + "public class JarClassLoaderJUnitFunction implements Function {"
-            + "public void init(Properties props) {}" + "public boolean hasResult() {return true;}"
-            + "public void execute(FunctionContext context) {context.getResultSender().lastResult(\"GOODv1\");}"
-            + "public String getId() {return \"JarClassLoaderJUnitFunction\";}"
-            + "public boolean optimizeForWrite() {return false;}"
-            + "public boolean isHA() {return false;}}";
-
-    byte[] jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnit.jar", jarBytes);
-
-    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
-    assertThat(function).isNotNull();
-    TestResultSender resultSender = new TestResultSender();
-    FunctionContext functionContext =
-        new FunctionContextImpl(null, function.getId(), null, resultSender);
-    function.execute(functionContext);
-    assertThat(resultSender.getResults()).isEqualTo("GOODv1");
-
-    // Test updating the function with a new JAR file
-    functionString = functionString.replace("v1", "v2");
-    jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnit.jar", jarBytes);
-
-    function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
-    assertThat(function).isNotNull();
-    resultSender = new TestResultSender();
-    functionContext = new FunctionContextImpl(null, function.getId(), null, resultSender);
-    function.execute(functionContext);
-    assertThat(resultSender.getResults()).isEqualTo("GOODv2");
-
-    // Test returning null for the Id
-    String functionNullIdString =
-        functionString.replace("return \"JarClassLoaderJUnitFunction\"", "return null");
-    jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction",
-        functionNullIdString);
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnit.jar", jarBytes);
-
-    assertThat(FunctionService.getFunction("JarClassLoaderJUnitFunction")).isNull();
-
-    // Test removing the JAR
-    ClassPathLoader.getLatest().getJarDeployer().undeploy("JarClassLoaderJUnit.jar");
-    assertThat(FunctionService.getFunction("JarClassLoaderJUnitFunction")).isNull();
+  private void givenUnexpectedJarFileContents() throws IOException {
+    FileUtils.deleteQuietly(jarFile);
+    jarBuilder.buildJarFromClassNames(jarFile, "UnexpectedClass");
   }
 
-  /**
-   * Ensure that abstract functions aren't added to the Function Service.
-   */
-  @Test
-  public void testAbstractFunction() throws Exception {
-    // Add an abstract Function to the Classpath
-    String functionString = "import org.apache.geode.cache.execute.Function;"
-        + "public abstract class JarClassLoaderJUnitFunction implements Function {"
-        + "public String getId() {return \"JarClassLoaderJUnitFunction\";}}";
-
-    byte[] jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitFunction.jar",
-        jarBytes);
-
-    ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunction");
-
-    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
-    assertThat(function).isNull();
-  }
-
-  @Test
-  public void testDeclarableFunctionsWithNoCacheXml() throws Exception {
-    final String jarName = "JarClassLoaderJUnitNoXml.jar";
-
-    // Add a Declarable Function without parameters for the class to the Classpath
-    String functionString =
-        "import java.util.Properties;" + "import org.apache.geode.cache.Declarable;"
-            + "import org.apache.geode.cache.execute.Function;"
-            + "import org.apache.geode.cache.execute.FunctionContext;"
-            + "public class JarClassLoaderJUnitFunctionNoXml implements Function, Declarable {"
-            + "public String getId() {return \"JarClassLoaderJUnitFunctionNoXml\";}"
-            + "public void init(Properties props) {}"
-            + "public void execute(FunctionContext context) {context.getResultSender().lastResult(\"NOPARMSv1\");}"
-            + "public boolean hasResult() {return true;}"
-            + "public boolean optimizeForWrite() {return false;}"
-            + "public boolean isHA() {return false;}}";
-
-    byte[] jarBytes = this.classBuilder
-        .createJarFromClassContent("JarClassLoaderJUnitFunctionNoXml", functionString);
-
-    ClassPathLoader.getLatest().getJarDeployer().deploy(jarName, jarBytes);
-
-    ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunctionNoXml");
-
-    // Check to see if the function without parameters executes correctly
-    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunctionNoXml");
-    assertThat(function).isNotNull();
-    TestResultSender resultSender = new TestResultSender();
-    function.execute(new FunctionContextImpl(null, function.getId(), null, resultSender));
-    assertThat((String) resultSender.getResults()).isEqualTo("NOPARMSv1");
-  }
-
-  @Test
-  public void testDependencyBetweenJars() throws Exception {
-    final File parentJarFile = temporaryFolder.newFile("JarClassLoaderJUnitParent.jar");
-    final File usesJarFile = temporaryFolder.newFile("JarClassLoaderJUnitUses.jar");
-
-    // Write out a JAR files.
-    StringBuffer stringBuffer = new StringBuffer();
-    stringBuffer.append("package jcljunit.parent;");
-    stringBuffer.append("public class JarClassLoaderJUnitParent {");
-    stringBuffer.append("public String getValueParent() {");
-    stringBuffer.append("return \"PARENT\";}}");
-
-    byte[] jarBytes = this.classBuilder.createJarFromClassContent(
-        "jcljunit/parent/JarClassLoaderJUnitParent", stringBuffer.toString());
-    writeJarBytesToFile(parentJarFile, jarBytes);
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitParent.jar", jarBytes);
-
-    stringBuffer = new StringBuffer();
-    stringBuffer.append("package jcljunit.uses;");
-    stringBuffer.append("public class JarClassLoaderJUnitUses {");
-    stringBuffer.append("public String getValueUses() {");
-    stringBuffer.append("return \"USES\";}}");
-
-    jarBytes = this.classBuilder.createJarFromClassContent("jcljunit/uses/JarClassLoaderJUnitUses",
-        stringBuffer.toString());
-    writeJarBytesToFile(usesJarFile, jarBytes);
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitUses.jar", jarBytes);
-
-    stringBuffer = new StringBuffer();
-    stringBuffer.append("package jcljunit.function;");
-    stringBuffer.append("import jcljunit.parent.JarClassLoaderJUnitParent;");
-    stringBuffer.append("import jcljunit.uses.JarClassLoaderJUnitUses;");
-    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
-    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
-    stringBuffer.append(
-        "public class JarClassLoaderJUnitFunction  extends JarClassLoaderJUnitParent implements Function {");
-    stringBuffer.append("private JarClassLoaderJUnitUses uses = new JarClassLoaderJUnitUses();");
-    stringBuffer.append("public boolean hasResult() {return true;}");
-    stringBuffer.append(
-        "public void execute(FunctionContext context) {context.getResultSender().lastResult(getValueParent() + \":\" + uses.getValueUses());}");
-    stringBuffer.append("public String getId() {return \"JarClassLoaderJUnitFunction\";}");
-    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
-    stringBuffer.append("public boolean isHA() {return false;}}");
-
-    ClassBuilder functionClassBuilder = new ClassBuilder();
-    functionClassBuilder.addToClassPath(parentJarFile.getAbsolutePath());
-    functionClassBuilder.addToClassPath(usesJarFile.getAbsolutePath());
-    jarBytes = functionClassBuilder.createJarFromClassContent(
-        "jcljunit/function/JarClassLoaderJUnitFunction", stringBuffer.toString());
-
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitFunction.jar",
-        jarBytes);
-
-    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
-    assertThat(function).isNotNull();
-    TestResultSender resultSender = new TestResultSender();
-    FunctionContext functionContext =
-        new FunctionContextImpl(null, function.getId(), null, resultSender);
-    function.execute(functionContext);
-    assertThat((String) resultSender.getResults()).isEqualTo("PARENT:USES");
-  }
-
-  @Test
-  public void testFindResource() throws IOException, ClassNotFoundException {
-    final String fileName = "file.txt";
-    final String fileContent = "FILE CONTENT";
-
-    byte[] jarBytes = this.classBuilder.createJarFromFileContent(fileName, fileContent);
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitResource.jar",
-        jarBytes);
-
-    InputStream inputStream = ClassPathLoader.getLatest().getResourceAsStream(fileName);
-    assertThat(inputStream).isNotNull();
-
-    final byte[] fileBytes = new byte[fileContent.length()];
-    inputStream.read(fileBytes);
-    inputStream.close();
-    assertThat(fileContent).isEqualTo(new String(fileBytes));
-  }
-
-  @Test
-  public void testUpdateClassInJar() throws Exception {
-    // First use of the JAR file
-    byte[] jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitTestClass",
-        "public class JarClassLoaderJUnitTestClass { public Integer getValue5() { return new Integer(5); } }");
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitUpdate.jar", jarBytes);
-
-    Class<?> clazz = ClassPathLoader.getLatest().forName("JarClassLoaderJUnitTestClass");
-    Object object = clazz.newInstance();
-    Method getValue5Method = clazz.getMethod("getValue5");
-    Integer value = (Integer) getValue5Method.invoke(object);
-    assertThat(value).isEqualTo(5);
-
-    // Now create an updated JAR file and make sure that the method from the new
-    // class is available.
-    jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitTestClass",
-        "public class JarClassLoaderJUnitTestClass { public Integer getValue10() { return new Integer(10); } }");
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitUpdate.jar", jarBytes);
-
-    clazz = ClassPathLoader.getLatest().forName("JarClassLoaderJUnitTestClass");
-    object = clazz.newInstance();
-    Method getValue10Method = clazz.getMethod("getValue10");
-    value = (Integer) getValue10Method.invoke(object);
-    assertThat(value).isEqualTo(10);
-  }
-
-  @Test
-  public void testMultiThreadingDoesNotCauseDeadlock() throws Exception {
-    // Add two JARs to the classpath
-    byte[] jarBytes = this.classBuilder.createJarFromName("JarClassLoaderJUnitA");
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitA.jar", jarBytes);
-
-    jarBytes = this.classBuilder.createJarFromClassContent("com/jcljunit/JarClassLoaderJUnitB",
-        "package com.jcljunit; public class JarClassLoaderJUnitB {}");
-    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitB.jar", jarBytes);
-
-    String[] classNames = new String[] {"JarClassLoaderJUnitA", "com.jcljunit.JarClassLoaderJUnitB",
-        "NON-EXISTENT CLASS"};
-
-    final int threadCount = 10;
-    ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
-    for (int i = 0; i < threadCount; i++) {
-      executorService.submit(new ForNameExerciser(classNames));
-    }
-
-    executorService.shutdown();
-    Awaitility.await().atMost(60, TimeUnit.SECONDS).until(executorService::isTerminated);
-
-    ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
-    long[] threadIds = threadMXBean.findDeadlockedThreads();
-
-    if (threadIds != null) {
-      StringBuilder deadLockTrace = new StringBuilder();
-      for (long threadId : threadIds) {
-        ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId, 100);
-        deadLockTrace.append(threadInfo.getThreadName()).append("\n");
-        for (StackTraceElement stackTraceElem : threadInfo.getStackTrace()) {
-          deadLockTrace.append("\t").append(stackTraceElem).append("\n");
-        }
-      }
-      System.out.println(deadLockTrace);
-    }
-    assertThat(threadIds).isNull();
-  }
-
-  private void writeJarBytesToFile(File jarFile, byte[] jarBytes) throws IOException {
-    final OutputStream outStream = new FileOutputStream(jarFile);
-    outStream.write(jarBytes);
-    outStream.close();
-  }
-
-  private static class TestResultSender implements ResultSender<Object> {
-    private Object result;
-
-    public TestResultSender() {}
-
-    protected Object getResults() {
-      return this.result;
-    }
-
-    @Override
-    public void lastResult(final Object lastResult) {
-      this.result = lastResult;
-    }
-
-    @Override
-    public void sendResult(final Object oneResult) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendException(final Throwable t) {
-      throw new UnsupportedOperationException();
-    }
-  }
-
-  static final Random random = new Random();
-
-  private class ForNameExerciser implements Runnable {
-    private final int numLoops = 1000;
-    private final String[] classNames;
-
-    ForNameExerciser(final String[] classNames) {
-      this.classNames = classNames;
-    }
+  private byte[] givenInvalidJarBytes() throws IOException {
+    byte[] invalidJarBytes = "INVALID JAR CONTENT".getBytes();
+    FileUtils.writeByteArrayToFile(jarFile, invalidJarBytes);
 
-    @Override
-    public void run() {
-      for (int i = 0; i < this.numLoops; i++) {
-        try {
-          // Random select a name from the list of class names and try to load it
-          String className = this.classNames[random.nextInt(this.classNames.length)];
-          ClassPathLoader.getLatest().forName(className);
-        } catch (ClassNotFoundException expected) { // expected
-        } catch (Exception e) {
-          throw new RuntimeException(e);
-        }
-      }
-    }
+    return invalidJarBytes;
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/c5dd26b7/geode-core/src/test/java/org/apache/geode/internal/JarDeployerDeadlockTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/JarDeployerDeadlockTest.java b/geode-core/src/test/java/org/apache/geode/internal/JarDeployerDeadlockTest.java
new file mode 100644
index 0000000..7ff1774
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/JarDeployerDeadlockTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.internal;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.awaitility.Awaitility;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+
+import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.test.compiler.JarBuilder;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+
+@Category(IntegrationTest.class)
+public class JarDeployerDeadlockTest {
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+  @Rule
+  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+  private ClassBuilder classBuilder;
+
+  @Before
+  public void setup() throws Exception {
+    File workingDir = temporaryFolder.newFolder();
+    ClassPathLoader.setLatestToDefault(workingDir);
+    classBuilder = new ClassBuilder();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    for (String functionName : FunctionService.getRegisteredFunctions().keySet()) {
+      FunctionService.unregisterFunction(functionName);
+    }
+
+    ClassPathLoader.setLatestToDefault();
+  }
+
+  @Test
+  public void testMultiThreadingDoesNotCauseDeadlock() throws Exception {
+    // Add two JARs to the classpath
+    byte[] jarBytes = this.classBuilder.createJarFromName("JarClassLoaderJUnitA");
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitA.jar", jarBytes);
+
+    jarBytes = this.classBuilder.createJarFromClassContent("com/jcljunit/JarClassLoaderJUnitB",
+        "package com.jcljunit; public class JarClassLoaderJUnitB {}");
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitB.jar", jarBytes);
+
+    String[] classNames = new String[] {"JarClassLoaderJUnitA", "com.jcljunit.JarClassLoaderJUnitB",
+        "NON-EXISTENT CLASS"};
+
+    final int threadCount = 10;
+    ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
+    for (int i = 0; i < threadCount; i++) {
+      executorService.submit(new ForNameExerciser(classNames));
+    }
+
+    executorService.shutdown();
+    Awaitility.await().atMost(60, TimeUnit.SECONDS).until(executorService::isTerminated);
+
+    ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+    long[] threadIds = threadMXBean.findDeadlockedThreads();
+
+    if (threadIds != null) {
+      StringBuilder deadLockTrace = new StringBuilder();
+      for (long threadId : threadIds) {
+        ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId, 100);
+        deadLockTrace.append(threadInfo.getThreadName()).append("\n");
+        for (StackTraceElement stackTraceElem : threadInfo.getStackTrace()) {
+          deadLockTrace.append("\t").append(stackTraceElem).append("\n");
+        }
+      }
+      System.out.println(deadLockTrace);
+    }
+    assertThat(threadIds).isNull();
+  }
+
+  private class ForNameExerciser implements Runnable {
+    private final Random random = new Random();
+
+    private final int numLoops = 1000;
+    private final String[] classNames;
+
+    ForNameExerciser(final String[] classNames) {
+      this.classNames = classNames;
+    }
+
+    @Override
+    public void run() {
+      for (int i = 0; i < this.numLoops; i++) {
+        try {
+          // Random select a name from the list of class names and try to load it
+          String className = this.classNames[random.nextInt(this.classNames.length)];
+          ClassPathLoader.getLatest().forName(className);
+        } catch (ClassNotFoundException expected) { // expected
+        } catch (Exception e) {
+          throw new RuntimeException(e);
+        }
+      }
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5dd26b7/geode-core/src/test/java/org/apache/geode/management/DeployJarTestSuite.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/DeployJarTestSuite.java b/geode-core/src/test/java/org/apache/geode/management/DeployJarTestSuite.java
index 6dfab66..9a8348e 100644
--- a/geode-core/src/test/java/org/apache/geode/management/DeployJarTestSuite.java
+++ b/geode-core/src/test/java/org/apache/geode/management/DeployJarTestSuite.java
@@ -19,7 +19,7 @@ import org.apache.geode.internal.ClassPathLoaderTest;
 import org.apache.geode.internal.DeployedJarJUnitTest;
 import org.apache.geode.internal.JarDeployerIntegrationTest;
 import org.apache.geode.management.internal.cli.commands.DeployCommandRedeployDUnitTest;
-import org.apache.geode.management.internal.cli.commands.DeployCommandsDUnitTest;
+import org.apache.geode.management.internal.cli.commands.DeployWithGroupsDUnitTest;
 import org.apache.geode.management.internal.configuration.ClusterConfigDeployJarDUnitTest;
 import org.junit.Ignore;
 import org.junit.runner.RunWith;
@@ -28,7 +28,7 @@ import org.junit.runners.Suite;
 
 @Ignore
 @RunWith(Suite.class)
-@Suite.SuiteClasses({DeployedJarJUnitTest.class, DeployCommandsDUnitTest.class,
+@Suite.SuiteClasses({DeployedJarJUnitTest.class, DeployWithGroupsDUnitTest.class,
     JarDeployerIntegrationTest.class, ClassPathLoaderIntegrationTest.class,
     ClassPathLoaderTest.class, DeployCommandRedeployDUnitTest.class,
     ClusterConfigDeployJarDUnitTest.class})

http://git-wip-us.apache.org/repos/asf/geode/blob/c5dd26b7/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandsDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandsDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandsDUnitTest.java
deleted file mode 100644
index 89148d7..0000000
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandsDUnitTest.java
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * 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.junit.experimental.categories.Category;
-
-import org.apache.geode.internal.ClassBuilder;
-import org.apache.geode.internal.ClassPathLoader;
-import org.apache.geode.test.dunit.rules.GfshShellConnectionRule;
-import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
-import org.apache.geode.test.dunit.rules.MemberVM;
-import org.apache.geode.test.junit.categories.DistributedTest;
-import org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder;
-
-/**
- * Unit tests for the DeployCommands class
- * 
- * @since GemFire 7.0
- */
-@SuppressWarnings("serial")
-@Category(DistributedTest.class)
-public class DeployCommandsDUnitTest 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 LocatorServerStartupRule lsRule = new LocatorServerStartupRule();
-
-  @Rule
-  public transient GfshShellConnectionRule gfshConnector = new GfshShellConnectionRule();
-
-  @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.executeAndVerifyCommand("deploy --jar=" + jar2 + " --group=" + GROUP1);
-    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.executeAndVerifyCommand(
-        "deploy --group=" + GROUP1 + " --dir=" + subdirWithJars3and4.getCanonicalPath());
-    String resultString = gfshConnector.getGfshOutput();
-
-    assertThat(resultString).describedAs(resultString).contains(server1.getName());
-    assertThat(resultString).doesNotContain(server2.getName());
-    assertThat(resultString).contains(jarName3);
-    assertThat(resultString).contains(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.executeAndVerifyCommand("undeploy --group=" + GROUP1);
-    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.executeAndVerifyCommand("deploy --group=" + GROUP1 + " --jars="
-        + jar3.getAbsolutePath() + "," + jar4.getAbsolutePath());
-    String resultString = gfshConnector.getGfshOutput();
-
-    assertThat(resultString).describedAs(resultString).contains(server1.getName());
-    assertThat(resultString).doesNotContain(server2.getName());
-    assertThat(resultString).contains(jarName3);
-    assertThat(resultString).contains(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.executeAndVerifyCommand("undeploy --jars=" + jarName3 + "," + jarName4);
-    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.executeAndVerifyCommand("deploy --jar=" + jar1);
-    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.executeAndVerifyCommand("undeploy --group=" + GROUP1);
-    server1.invoke(() -> assertThatCannotLoad(jarName1, class1));
-    server2.invoke(() -> assertThatCanLoad(jarName1, class1));
-  }
-
-  @Test
-  public void deployMultipleJarsToAllServers() throws Exception {
-    gfshConnector.executeAndVerifyCommand("deploy --dir=" + subdirWithJars3and4.getCanonicalPath());
-
-    server1.invoke(() -> {
-      assertThatCanLoad(jarName3, class3);
-      assertThatCanLoad(jarName4, class4);
-    });
-    server2.invoke(() -> {
-      assertThatCanLoad(jarName3, class3);
-      assertThatCanLoad(jarName4, class4);
-    });
-
-    gfshConnector.executeAndVerifyCommand("undeploy");
-
-    server1.invoke(() -> {
-      assertThatCannotLoad(jarName3, class3);
-      assertThatCannotLoad(jarName4, class4);
-    });
-    server2.invoke(() -> {
-      assertThatCannotLoad(jarName3, class3);
-      assertThatCannotLoad(jarName4, class4);
-    });
-  }
-
-  @Test
-  public void undeployOfMultipleJars() throws Exception {
-    gfshConnector.executeAndVerifyCommand("deploy --dir=" + subdirWithJars3and4.getCanonicalPath());
-
-    server1.invoke(() -> {
-      assertThatCanLoad(jarName3, class3);
-      assertThatCanLoad(jarName4, class4);
-    });
-    server2.invoke(() -> {
-      assertThatCanLoad(jarName3, class3);
-      assertThatCanLoad(jarName4, class4);
-    });
-
-    gfshConnector
-        .executeAndVerifyCommand("undeploy --jar=" + jar3.getName() + "," + jar4.getName());
-    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().findDeployedJar(jarName)).isNotNull();
-    assertThat(ClassPathLoader.getLatest().forName(className)).isNotNull();
-  }
-
-  private void assertThatCannotLoad(String jarName, String className) {
-    assertThat(ClassPathLoader.getLatest().getJarDeployer().findDeployedJar(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
-        .executeAndVerifyCommand("deploy --group=" + GROUP1 + " --jar=" + jar1.getCanonicalPath());
-    gfshConnector
-        .executeAndVerifyCommand("deploy --group=" + GROUP2 + " --jar=" + jar2.getCanonicalPath());
-
-    // List for all members
-    gfshConnector.executeAndVerifyCommand("list deployed");
-    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.executeAndVerifyCommand("list deployed --group=" + GROUP1);
-    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.executeAndVerifyCommand("list deployed --group=" + GROUP2);
-    resultString = gfshConnector.getGfshOutput();
-    assertThat(resultString).doesNotContain(server1.getName());
-    assertThat(resultString).contains(server2.getName());
-
-    assertThat(resultString).doesNotContain(jarName1);
-    assertThat(resultString).contains(jarName2);
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5dd26b7/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployWithGroupsDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployWithGroupsDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployWithGroupsDUnitTest.java
new file mode 100644
index 0000000..8db7275
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployWithGroupsDUnitTest.java
@@ -0,0 +1,303 @@
+/*
+ * 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.junit.experimental.categories.Category;
+
+import org.apache.geode.internal.ClassBuilder;
+import org.apache.geode.internal.ClassPathLoader;
+import org.apache.geode.test.dunit.rules.GfshShellConnectionRule;
+import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder;
+
+/**
+ * Unit tests for the DeployCommands class
+ * 
+ * @since GemFire 7.0
+ */
+@SuppressWarnings("serial")
+@Category(DistributedTest.class)
+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 LocatorServerStartupRule lsRule = new LocatorServerStartupRule();
+
+  @Rule
+  public transient GfshShellConnectionRule gfshConnector = new GfshShellConnectionRule();
+
+  @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.executeAndVerifyCommand("deploy --jar=" + jar2 + " --group=" + GROUP1);
+    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.executeAndVerifyCommand(
+        "deploy --group=" + GROUP1 + " --dir=" + subdirWithJars3and4.getCanonicalPath());
+    String resultString = gfshConnector.getGfshOutput();
+
+    assertThat(resultString).describedAs(resultString).contains(server1.getName());
+    assertThat(resultString).doesNotContain(server2.getName());
+    assertThat(resultString).contains(jarName3);
+    assertThat(resultString).contains(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.executeAndVerifyCommand("undeploy --group=" + GROUP1);
+    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.executeAndVerifyCommand("deploy --group=" + GROUP1 + " --jars="
+        + jar3.getAbsolutePath() + "," + jar4.getAbsolutePath());
+    String resultString = gfshConnector.getGfshOutput();
+
+    assertThat(resultString).describedAs(resultString).contains(server1.getName());
+    assertThat(resultString).doesNotContain(server2.getName());
+    assertThat(resultString).contains(jarName3);
+    assertThat(resultString).contains(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.executeAndVerifyCommand("undeploy --jars=" + jarName3 + "," + jarName4);
+    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.executeAndVerifyCommand("deploy --jar=" + jar1);
+    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.executeAndVerifyCommand("undeploy --group=" + GROUP1);
+    server1.invoke(() -> assertThatCannotLoad(jarName1, class1));
+    server2.invoke(() -> assertThatCanLoad(jarName1, class1));
+  }
+
+  @Test
+  public void deployMultipleJarsToAllServers() throws Exception {
+    gfshConnector.executeAndVerifyCommand("deploy --dir=" + subdirWithJars3and4.getCanonicalPath());
+
+    server1.invoke(() -> {
+      assertThatCanLoad(jarName3, class3);
+      assertThatCanLoad(jarName4, class4);
+    });
+    server2.invoke(() -> {
+      assertThatCanLoad(jarName3, class3);
+      assertThatCanLoad(jarName4, class4);
+    });
+
+    gfshConnector.executeAndVerifyCommand("undeploy");
+
+    server1.invoke(() -> {
+      assertThatCannotLoad(jarName3, class3);
+      assertThatCannotLoad(jarName4, class4);
+    });
+    server2.invoke(() -> {
+      assertThatCannotLoad(jarName3, class3);
+      assertThatCannotLoad(jarName4, class4);
+    });
+  }
+
+  @Test
+  public void undeployOfMultipleJars() throws Exception {
+    gfshConnector.executeAndVerifyCommand("deploy --dir=" + subdirWithJars3and4.getCanonicalPath());
+
+    server1.invoke(() -> {
+      assertThatCanLoad(jarName3, class3);
+      assertThatCanLoad(jarName4, class4);
+    });
+    server2.invoke(() -> {
+      assertThatCanLoad(jarName3, class3);
+      assertThatCanLoad(jarName4, class4);
+    });
+
+    gfshConnector
+        .executeAndVerifyCommand("undeploy --jar=" + jar3.getName() + "," + jar4.getName());
+    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().findDeployedJar(jarName)).isNotNull();
+    assertThat(ClassPathLoader.getLatest().forName(className)).isNotNull();
+  }
+
+  private void assertThatCannotLoad(String jarName, String className) {
+    assertThat(ClassPathLoader.getLatest().getJarDeployer().findDeployedJar(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
+        .executeAndVerifyCommand("deploy --group=" + GROUP1 + " --jar=" + jar1.getCanonicalPath());
+    gfshConnector
+        .executeAndVerifyCommand("deploy --group=" + GROUP2 + " --jar=" + jar2.getCanonicalPath());
+
+    // List for all members
+    gfshConnector.executeAndVerifyCommand("list deployed");
+    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.executeAndVerifyCommand("list deployed --group=" + GROUP1);
+    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.executeAndVerifyCommand("list deployed --group=" + GROUP2);
+    resultString = gfshConnector.getGfshOutput();
+    assertThat(resultString).doesNotContain(server1.getName());
+    assertThat(resultString).contains(server2.getName());
+
+    assertThat(resultString).doesNotContain(jarName1);
+    assertThat(resultString).contains(jarName2);
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5dd26b7/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/CommandOverHttpDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/CommandOverHttpDUnitTest.java b/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/CommandOverHttpDUnitTest.java
index 7753aaf..e74830c 100644
--- a/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/CommandOverHttpDUnitTest.java
+++ b/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/CommandOverHttpDUnitTest.java
@@ -26,7 +26,7 @@ import org.apache.geode.test.junit.runner.SuiteRunner;
 
 @Category({DistributedTest.class, SecurityTest.class})
 @RunWith(SuiteRunner.class)
-@Suite.SuiteClasses({ConfigCommandsDUnitTest.class, DeployCommandsDUnitTest.class,
+@Suite.SuiteClasses({ConfigCommandsDUnitTest.class, DeployWithGroupsDUnitTest.class,
     DiskStoreCommandsDUnitTest.class, FunctionCommandsDUnitTest.class,
     GemfireDataCommandsDUnitTest.class,
     GetCommandOnRegionWithCacheLoaderDuringCacheMissDUnitTest.class,