You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2016/08/21 15:38:53 UTC

[1/4] mina-sshd git commit: [SSHD-691] Attempt to create server instance only once per test as much as possible

Repository: mina-sshd
Updated Branches:
  refs/heads/master b5bb002f0 -> ae8d1c995


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractCheckFileExtensionTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractCheckFileExtensionTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractCheckFileExtensionTest.java
index a47e5d2..9ddeb30 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractCheckFileExtensionTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractCheckFileExtensionTest.java
@@ -32,7 +32,6 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.sshd.client.SshClient;
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.client.subsystem.sftp.AbstractSftpClientTestSupport;
 import org.apache.sshd.client.subsystem.sftp.SftpClient;
@@ -52,7 +51,6 @@ import org.apache.sshd.common.util.Pair;
 import org.apache.sshd.common.util.buffer.BufferUtils;
 import org.apache.sshd.common.util.io.IoUtils;
 import org.apache.sshd.util.test.Utils;
-import org.junit.After;
 import org.junit.Before;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -125,11 +123,6 @@ public class AbstractCheckFileExtensionTest extends AbstractSftpClientTestSuppor
         setupServer();
     }
 
-    @After
-    public void tearDown() throws Exception {
-        tearDownServer();
-    }
-
     @Test
     public void testCheckFileExtension() throws Exception {
         testCheckFileExtension(algorithm, dataSize, blockSize);
@@ -169,7 +162,7 @@ public class AbstractCheckFileExtensionTest extends AbstractSftpClientTestSuppor
         Path srcFile = assertHierarchyTargetFolderExists(lclSftp).resolve(factory.getName() + "-data-" + data.length + "-" + hashBlockSize + ".txt");
         Files.write(srcFile, data, IoUtils.EMPTY_OPEN_OPTIONS);
 
-        List<String> algorithms = new ArrayList<String>(BuiltinDigests.VALUES.size());
+        List<String> algorithms = new ArrayList<>(BuiltinDigests.VALUES.size());
         // put the selected algorithm 1st and then the rest
         algorithms.add(factory.getName());
         for (NamedFactory<? extends Digest> f : BuiltinDigests.VALUES) {
@@ -183,40 +176,33 @@ public class AbstractCheckFileExtensionTest extends AbstractSftpClientTestSuppor
         Path parentPath = targetPath.getParent();
         String srcPath = Utils.resolveRelativeRemotePath(parentPath, srcFile);
         String srcFolder = Utils.resolveRelativeRemotePath(parentPath, srcFile.getParent());
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient()) {
+                CheckFileNameExtension file = assertExtensionCreated(sftp, CheckFileNameExtension.class);
+                try {
+                    Pair<String, ?> result = file.checkFileName(srcFolder, algorithms, 0L, 0L, hashBlockSize);
+                    fail("Unexpected success to hash folder=" + srcFolder + ": " + result.getFirst());
+                } catch (IOException e) {    // expected - not allowed to hash a folder
+                    assertTrue("Not an SftpException", e instanceof SftpException);
+                }
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    CheckFileNameExtension file = assertExtensionCreated(sftp, CheckFileNameExtension.class);
+                CheckFileHandleExtension hndl = assertExtensionCreated(sftp, CheckFileHandleExtension.class);
+                try (CloseableHandle dirHandle = sftp.openDir(srcFolder)) {
                     try {
-                        Pair<String, ?> result = file.checkFileName(srcFolder, algorithms, 0L, 0L, hashBlockSize);
-                        fail("Unexpected success to hash folder=" + srcFolder + ": " + result.getFirst());
+                        Pair<String, ?> result = hndl.checkFileHandle(dirHandle, algorithms, 0L, 0L, hashBlockSize);
+                        fail("Unexpected handle success on folder=" + srcFolder + ": " + result.getFirst());
                     } catch (IOException e) {    // expected - not allowed to hash a folder
                         assertTrue("Not an SftpException", e instanceof SftpException);
                     }
+                }
 
-                    CheckFileHandleExtension hndl = assertExtensionCreated(sftp, CheckFileHandleExtension.class);
-                    try (CloseableHandle dirHandle = sftp.openDir(srcFolder)) {
-                        try {
-                            Pair<String, ?> result = hndl.checkFileHandle(dirHandle, algorithms, 0L, 0L, hashBlockSize);
-                            fail("Unexpected handle success on folder=" + srcFolder + ": " + result.getFirst());
-                        } catch (IOException e) {    // expected - not allowed to hash a folder
-                            assertTrue("Not an SftpException", e instanceof SftpException);
-                        }
-                    }
-
-                    validateHashResult(file, file.checkFileName(srcPath, algorithms, 0L, 0L, hashBlockSize), algorithms.get(0), expectedHash);
-                    try (CloseableHandle fileHandle = sftp.open(srcPath, SftpClient.OpenMode.Read)) {
-                        validateHashResult(hndl, hndl.checkFileHandle(fileHandle, algorithms, 0L, 0L, hashBlockSize), algorithms.get(0), expectedHash);
-                    }
+                validateHashResult(file, file.checkFileName(srcPath, algorithms, 0L, 0L, hashBlockSize), algorithms.get(0), expectedHash);
+                try (CloseableHandle fileHandle = sftp.open(srcPath, SftpClient.OpenMode.Read)) {
+                    validateHashResult(hndl, hndl.checkFileHandle(fileHandle, algorithms, 0L, 0L, hashBlockSize), algorithms.get(0), expectedHash);
                 }
-            } finally {
-                client.stop();
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractMD5HashExtensionTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractMD5HashExtensionTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractMD5HashExtensionTest.java
index f39bf12..6c63b6f 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractMD5HashExtensionTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/AbstractMD5HashExtensionTest.java
@@ -30,7 +30,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.sshd.client.SshClient;
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.client.subsystem.sftp.AbstractSftpClientTestSupport;
 import org.apache.sshd.client.subsystem.sftp.SftpClient;
@@ -45,7 +44,6 @@ import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.buffer.BufferUtils;
 import org.apache.sshd.common.util.io.IoUtils;
 import org.apache.sshd.util.test.Utils;
-import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -92,11 +90,6 @@ public class AbstractMD5HashExtensionTest extends AbstractSftpClientTestSupport
         setupServer();
     }
 
-    @After
-    public void tearDown() throws Exception {
-        tearDownServer();
-    }
-
     @Test
     public void testMD5HashExtension() throws Exception {
         testMD5HashExtension(size);
@@ -138,50 +131,43 @@ public class AbstractMD5HashExtensionTest extends AbstractSftpClientTestSupport
         Path parentPath = targetPath.getParent();
         String srcPath = Utils.resolveRelativeRemotePath(parentPath, srcFile);
         String srcFolder = Utils.resolveRelativeRemotePath(parentPath, srcFile.getParent());
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient()) {
+                MD5FileExtension file = assertExtensionCreated(sftp, MD5FileExtension.class);
+                try {
+                    byte[] actual = file.getHash(srcFolder, 0L, 0L, quickHash);
+                    fail("Unexpected file success on folder=" + srcFolder + ": " + BufferUtils.toHex(':', actual));
+                } catch (IOException e) {    // expected - not allowed to hash a folder
+                    assertTrue("Not an SftpException for file hash on " + srcFolder, e instanceof SftpException);
+                }
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    MD5FileExtension file = assertExtensionCreated(sftp, MD5FileExtension.class);
+                MD5HandleExtension hndl = assertExtensionCreated(sftp, MD5HandleExtension.class);
+                try (CloseableHandle dirHandle = sftp.openDir(srcFolder)) {
                     try {
-                        byte[] actual = file.getHash(srcFolder, 0L, 0L, quickHash);
-                        fail("Unexpected file success on folder=" + srcFolder + ": " + BufferUtils.toHex(':', actual));
+                        byte[] actual = hndl.getHash(dirHandle, 0L, 0L, quickHash);
+                        fail("Unexpected handle success on folder=" + srcFolder + ": " + BufferUtils.toHex(':', actual));
                     } catch (IOException e) {    // expected - not allowed to hash a folder
-                        assertTrue("Not an SftpException for file hash on " + srcFolder, e instanceof SftpException);
-                    }
-
-                    MD5HandleExtension hndl = assertExtensionCreated(sftp, MD5HandleExtension.class);
-                    try (CloseableHandle dirHandle = sftp.openDir(srcFolder)) {
-                        try {
-                            byte[] actual = hndl.getHash(dirHandle, 0L, 0L, quickHash);
-                            fail("Unexpected handle success on folder=" + srcFolder + ": " + BufferUtils.toHex(':', actual));
-                        } catch (IOException e) {    // expected - not allowed to hash a folder
-                            assertTrue("Not an SftpException for handle hash on " + srcFolder, e instanceof SftpException);
-                        }
+                        assertTrue("Not an SftpException for handle hash on " + srcFolder, e instanceof SftpException);
                     }
+                }
 
-                    try (CloseableHandle fileHandle = sftp.open(srcPath, SftpClient.OpenMode.Read)) {
-                        for (byte[] qh : new byte[][]{GenericUtils.EMPTY_BYTE_ARRAY, quickHash}) {
-                            for (boolean useFile : new boolean[]{true, false}) {
-                                byte[] actualHash = useFile ? file.getHash(srcPath, 0L, 0L, qh) : hndl.getHash(fileHandle, 0L, 0L, qh);
-                                String type = useFile ? file.getClass().getSimpleName() : hndl.getClass().getSimpleName();
-                                if (!Arrays.equals(expectedHash, actualHash)) {
-                                    fail("Mismatched hash for quick=" + BufferUtils.toHex(':', qh)
-                                            + " using " + type + " on " + srcFile
-                                            + ": expected=" + BufferUtils.toHex(':', expectedHash)
-                                            + ", actual=" + BufferUtils.toHex(':', actualHash));
-                                }
+                try (CloseableHandle fileHandle = sftp.open(srcPath, SftpClient.OpenMode.Read)) {
+                    for (byte[] qh : new byte[][]{GenericUtils.EMPTY_BYTE_ARRAY, quickHash}) {
+                        for (boolean useFile : new boolean[]{true, false}) {
+                            byte[] actualHash = useFile ? file.getHash(srcPath, 0L, 0L, qh) : hndl.getHash(fileHandle, 0L, 0L, qh);
+                            String type = useFile ? file.getClass().getSimpleName() : hndl.getClass().getSimpleName();
+                            if (!Arrays.equals(expectedHash, actualHash)) {
+                                fail("Mismatched hash for quick=" + BufferUtils.toHex(':', qh)
+                                        + " using " + type + " on " + srcFile
+                                        + ": expected=" + BufferUtils.toHex(':', expectedHash)
+                                        + ", actual=" + BufferUtils.toHex(':', actualHash));
                             }
                         }
                     }
                 }
-            } finally {
-                client.stop();
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/CopyDataExtensionImplTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/CopyDataExtensionImplTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/CopyDataExtensionImplTest.java
index 2ae45a4..e2ba00d 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/CopyDataExtensionImplTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/CopyDataExtensionImplTest.java
@@ -34,7 +34,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.sshd.client.SshClient;
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.client.subsystem.sftp.AbstractSftpClientTestSupport;
 import org.apache.sshd.client.subsystem.sftp.SftpClient;
@@ -45,7 +44,6 @@ import org.apache.sshd.common.random.Random;
 import org.apache.sshd.common.subsystem.sftp.SftpConstants;
 import org.apache.sshd.common.util.io.IoUtils;
 import org.apache.sshd.util.test.Utils;
-import org.junit.After;
 import org.junit.Before;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -111,11 +109,6 @@ public class CopyDataExtensionImplTest extends AbstractSftpClientTestSupport {
         setupServer();
     }
 
-    @After
-    public void tearDown() throws Exception {
-        tearDownServer();
-    }
-
     @Test
     public void testCopyDataExtension() throws Exception {
         testCopyDataExtension(size, srcOffset, length, dstOffset);
@@ -151,37 +144,30 @@ public class CopyDataExtensionImplTest extends AbstractSftpClientTestSupport {
             Files.delete(dstFile);
         }
         String dstPath = Utils.resolveRelativeRemotePath(parentPath, dstFile);
-
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            if (writeOffset > 0L) {
-                Factory<? extends Random> factory = client.getRandomFactory();
-                Random randomizer = factory.create();
-                long totalLength = writeOffset + readLength;
-                byte[] workBuf = new byte[(int) Math.min(totalLength, IoUtils.DEFAULT_COPY_SIZE)];
-                try (OutputStream output = Files.newOutputStream(dstFile, IoUtils.EMPTY_OPEN_OPTIONS)) {
-                    while (totalLength > 0L) {
-                        randomizer.fill(workBuf);
-                        output.write(workBuf);
-                        totalLength -= workBuf.length;
-                    }
+        if (writeOffset > 0L) {
+            Factory<? extends Random> factory = client.getRandomFactory();
+            Random randomizer = factory.create();
+            long totalLength = writeOffset + readLength;
+            byte[] workBuf = new byte[(int) Math.min(totalLength, IoUtils.DEFAULT_COPY_SIZE)];
+            try (OutputStream output = Files.newOutputStream(dstFile, IoUtils.EMPTY_OPEN_OPTIONS)) {
+                while (totalLength > 0L) {
+                    randomizer.fill(workBuf);
+                    output.write(workBuf);
+                    totalLength -= workBuf.length;
                 }
             }
+        }
 
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-                try (SftpClient sftp = session.createSftpClient()) {
-                    CopyDataExtension ext = assertExtensionCreated(sftp, CopyDataExtension.class);
-                    try (CloseableHandle readHandle = sftp.open(srcPath, SftpClient.OpenMode.Read);
-                         CloseableHandle writeHandle = sftp.open(dstPath, SftpClient.OpenMode.Write, SftpClient.OpenMode.Create)) {
-                        ext.copyData(readHandle, readOffset, readLength, writeHandle, writeOffset);
-                    }
+            try (SftpClient sftp = session.createSftpClient()) {
+                CopyDataExtension ext = assertExtensionCreated(sftp, CopyDataExtension.class);
+                try (CloseableHandle readHandle = sftp.open(srcPath, SftpClient.OpenMode.Read);
+                     CloseableHandle writeHandle = sftp.open(dstPath, SftpClient.OpenMode.Write, SftpClient.OpenMode.Create)) {
+                    ext.copyData(readHandle, readOffset, readLength, writeHandle, writeOffset);
                 }
-            } finally {
-                client.stop();
             }
         }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/CopyFileExtensionImplTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/CopyFileExtensionImplTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/CopyFileExtensionImplTest.java
index e929f47..f1acc08 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/CopyFileExtensionImplTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/CopyFileExtensionImplTest.java
@@ -26,7 +26,6 @@ import java.nio.file.LinkOption;
 import java.nio.file.Path;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.sshd.client.SshClient;
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.client.subsystem.sftp.AbstractSftpClientTestSupport;
 import org.apache.sshd.client.subsystem.sftp.SftpClient;
@@ -35,7 +34,6 @@ import org.apache.sshd.common.subsystem.sftp.SftpConstants;
 import org.apache.sshd.common.subsystem.sftp.SftpException;
 import org.apache.sshd.common.util.io.IoUtils;
 import org.apache.sshd.util.test.Utils;
-import org.junit.After;
 import org.junit.Before;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -55,11 +53,6 @@ public class CopyFileExtensionImplTest extends AbstractSftpClientTestSupport {
         setupServer();
     }
 
-    @After
-    public void tearDown() throws Exception {
-        tearDownServer();
-    }
-
     @Test
     public void testCopyFileExtension() throws Exception {
         Path targetPath = detectTargetFolder();
@@ -78,31 +71,25 @@ public class CopyFileExtensionImplTest extends AbstractSftpClientTestSupport {
         LinkOption[] options = IoUtils.getLinkOptions(false);
         assertFalse("Destination file unexpectedly exists", Files.exists(dstFile, options));
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+            try (SftpClient sftp = session.createSftpClient()) {
+                CopyFileExtension ext = assertExtensionCreated(sftp, CopyFileExtension.class);
+                ext.copyFile(srcPath, dstPath, false);
+                assertTrue("Source file not preserved", Files.exists(srcFile, options));
+                assertTrue("Destination file not created", Files.exists(dstFile, options));
 
-                try (SftpClient sftp = session.createSftpClient()) {
-                    CopyFileExtension ext = assertExtensionCreated(sftp, CopyFileExtension.class);
-                    ext.copyFile(srcPath, dstPath, false);
-                    assertTrue("Source file not preserved", Files.exists(srcFile, options));
-                    assertTrue("Destination file not created", Files.exists(dstFile, options));
+                byte[] actual = Files.readAllBytes(dstFile);
+                assertArrayEquals("Mismatched copied data", data, actual);
 
-                    byte[] actual = Files.readAllBytes(dstFile);
-                    assertArrayEquals("Mismatched copied data", data, actual);
-
-                    try {
-                        ext.copyFile(srcPath, dstPath, false);
-                        fail("Unexpected success to overwrite existing destination: " + dstFile);
-                    } catch (IOException e) {
-                        assertTrue("Not an SftpException", e instanceof SftpException);
-                    }
+                try {
+                    ext.copyFile(srcPath, dstPath, false);
+                    fail("Unexpected success to overwrite existing destination: " + dstFile);
+                } catch (IOException e) {
+                    assertTrue("Not an SftpException", e instanceof SftpException);
                 }
-            } finally {
-                client.stop();
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/SpaceAvailableExtensionImplTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/SpaceAvailableExtensionImplTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/SpaceAvailableExtensionImplTest.java
index e8affed..ef1cb61 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/SpaceAvailableExtensionImplTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/helpers/SpaceAvailableExtensionImplTest.java
@@ -25,9 +25,9 @@ import java.nio.file.FileStore;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.sshd.client.SshClient;
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.client.subsystem.sftp.AbstractSftpClientTestSupport;
 import org.apache.sshd.client.subsystem.sftp.SftpClient;
@@ -39,7 +39,6 @@ import org.apache.sshd.server.Command;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystem;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
 import org.apache.sshd.util.test.Utils;
-import org.junit.After;
 import org.junit.Before;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -59,11 +58,6 @@ public class SpaceAvailableExtensionImplTest extends AbstractSftpClientTestSuppo
         setupServer();
     }
 
-    @After
-    public void tearDown() throws Exception {
-        tearDownServer();
-    }
-
     @Test
     public void testFileStoreReport() throws Exception {
         Path targetPath = detectTargetFolder();
@@ -72,6 +66,8 @@ public class SpaceAvailableExtensionImplTest extends AbstractSftpClientTestSuppo
         FileStore store = Files.getFileStore(lclSftp.getRoot());
         final String queryPath = Utils.resolveRelativeRemotePath(parentPath, lclSftp);
         final SpaceAvailableExtensionInfo expected = new SpaceAvailableExtensionInfo(store);
+
+        List<NamedFactory<Command>> factories = sshd.getSubsystemFactories();
         sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystemFactory() {
             @Override
             public Command create() {
@@ -88,21 +84,17 @@ public class SpaceAvailableExtensionImplTest extends AbstractSftpClientTestSuppo
             }
         }));
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-                try (SftpClient sftp = session.createSftpClient()) {
-                    SpaceAvailableExtension ext = assertExtensionCreated(sftp, SpaceAvailableExtension.class);
-                    SpaceAvailableExtensionInfo actual = ext.available(queryPath);
-                    assertEquals("Mismatched information", expected, actual);
-                }
-            } finally {
-                client.stop();
+            try (SftpClient sftp = session.createSftpClient()) {
+                SpaceAvailableExtension ext = assertExtensionCreated(sftp, SpaceAvailableExtension.class);
+                SpaceAvailableExtensionInfo actual = ext.available(queryPath);
+                assertEquals("Mismatched information", expected, actual);
             }
+        } finally {
+            sshd.setSubsystemFactories(factories);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/helpers/OpenSSHExtensionsTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/helpers/OpenSSHExtensionsTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/helpers/OpenSSHExtensionsTest.java
index 7a6223c..d69813e 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/helpers/OpenSSHExtensionsTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/helpers/OpenSSHExtensionsTest.java
@@ -54,7 +54,6 @@ import org.apache.sshd.server.session.ServerSession;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystem;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
 import org.apache.sshd.util.test.Utils;
-import org.junit.After;
 import org.junit.Before;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -74,11 +73,6 @@ public class OpenSSHExtensionsTest extends AbstractSftpClientTestSupport {
         setupServer();
     }
 
-    @After
-    public void tearDown() throws Exception {
-        tearDownServer();
-    }
-
     @Test
     public void testFsync() throws IOException {
         Path targetPath = detectTargetFolder();
@@ -88,25 +82,19 @@ public class OpenSSHExtensionsTest extends AbstractSftpClientTestSupport {
 
         Path parentPath = targetPath.getParent();
         String srcPath = Utils.resolveRelativeRemotePath(parentPath, srcFile);
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    OpenSSHFsyncExtension fsync = assertExtensionCreated(sftp, OpenSSHFsyncExtension.class);
-                    try (CloseableHandle fileHandle = sftp.open(srcPath, SftpClient.OpenMode.Write, SftpClient.OpenMode.Create)) {
-                        sftp.write(fileHandle, 0L, expected);
-                        fsync.fsync(fileHandle);
-
-                        byte[] actual = Files.readAllBytes(srcFile);
-                        assertArrayEquals("Mismatched written data", expected, actual);
-                    }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient()) {
+                OpenSSHFsyncExtension fsync = assertExtensionCreated(sftp, OpenSSHFsyncExtension.class);
+                try (CloseableHandle fileHandle = sftp.open(srcPath, SftpClient.OpenMode.Write, SftpClient.OpenMode.Create)) {
+                    sftp.write(fileHandle, 0L, expected);
+                    fsync.fsync(fileHandle);
+
+                    byte[] actual = Files.readAllBytes(srcFile);
+                    assertArrayEquals("Mismatched written data", expected, actual);
                 }
-            } finally {
-                client.stop();
             }
         }
     }
@@ -120,7 +108,7 @@ public class OpenSSHExtensionsTest extends AbstractSftpClientTestSupport {
         Path parentPath = targetPath.getParent();
         String srcPath = Utils.resolveRelativeRemotePath(parentPath, srcFile);
 
-        final AtomicReference<String> extensionHolder = new AtomicReference<String>(null);
+        final AtomicReference<String> extensionHolder = new AtomicReference<>(null);
         final OpenSSHStatExtensionInfo expected = new OpenSSHStatExtensionInfo();
         expected.f_bavail = Short.MAX_VALUE;
         expected.f_bfree = Integer.MAX_VALUE;
@@ -142,7 +130,7 @@ public class OpenSSHExtensionsTest extends AbstractSftpClientTestSupport {
                     protected List<OpenSSHExtension> resolveOpenSSHExtensions(ServerSession session) {
                         List<OpenSSHExtension> original = super.resolveOpenSSHExtensions(session);
                         int numOriginal = GenericUtils.size(original);
-                        List<OpenSSHExtension> result = new ArrayList<OpenSSHExtension>(numOriginal + 2);
+                        List<OpenSSHExtension> result = new ArrayList<>(numOriginal + 2);
                         if (numOriginal > 0) {
                             result.addAll(original);
                         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/cipher/CipherTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/CipherTest.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/CipherTest.java
index d47019b..36883cc 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/cipher/CipherTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/CipherTest.java
@@ -39,6 +39,7 @@ import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.JSchLogger;
 import org.apache.sshd.util.test.SimpleUserInfo;
 import org.apache.sshd.util.test.Utils;
+import org.junit.AfterClass;
 import org.junit.Assume;
 import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
@@ -87,6 +88,8 @@ public class CipherTest extends BaseTestSupport {
             });
 
     private static final String CRYPT_NAMES = NamedResource.Utils.getNames(TEST_CIPHERS);
+    private static SshServer sshd;
+    private static int port;
 
     private final Random random = Utils.getRandomizerInstance();
     private final BuiltinCiphers builtInCipher;
@@ -105,26 +108,31 @@ public class CipherTest extends BaseTestSupport {
     }
 
     @BeforeClass
-    public static void jschInit() {
+    public static void setupClientAndServer() throws Exception {
         JSchLogger.init();
+        sshd = Utils.setupTestServer(CipherTest.class);
+        sshd.start();
+        port = sshd.getPort();
     }
 
-    @Test
-    public void testBuiltinCipherSession() throws Exception {
-        Assume.assumeTrue("No internal support for " + builtInCipher.getName(), builtInCipher.isSupported() && checkCipher(jschCipher.getName()));
-
-        try (SshServer sshd = setupTestServer()) {
-            sshd.setCipherFactories(Collections.<NamedFactory<org.apache.sshd.common.cipher.Cipher>>singletonList(builtInCipher));
-            sshd.start();
-
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
+        if (sshd != null) {
             try {
-                runJschTest(sshd.getPort());
-            } finally {
                 sshd.stop(true);
+            } finally {
+                sshd = null;
             }
         }
     }
 
+    @Test
+    public void testBuiltinCipherSession() throws Exception {
+        Assume.assumeTrue("No internal support for " + builtInCipher.getName(), builtInCipher.isSupported() && checkCipher(jschCipher.getName()));
+        sshd.setCipherFactories(Collections.<NamedFactory<org.apache.sshd.common.cipher.Cipher>>singletonList(builtInCipher));
+        runJschTest(port);
+    }
+
     private void runJschTest(int port) throws Exception {
         JSch sch = new JSch();
         JSch.setConfig("cipher.s2c", CRYPT_NAMES);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/compression/CompressionTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/compression/CompressionTest.java b/sshd-core/src/test/java/org/apache/sshd/common/compression/CompressionTest.java
index 4ded562..59f2af9 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/compression/CompressionTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/compression/CompressionTest.java
@@ -32,13 +32,16 @@ import com.jcraft.jsch.JSch;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.channel.Channel;
 import org.apache.sshd.common.kex.KexProposalOption;
+import org.apache.sshd.common.mac.MacTest;
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.session.SessionListener;
 import org.apache.sshd.server.SshServer;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.JSchLogger;
 import org.apache.sshd.util.test.SimpleUserInfo;
+import org.apache.sshd.util.test.Utils;
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Assume;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -60,11 +63,26 @@ public class CompressionTest extends BaseTestSupport {
     private static final Collection<KexProposalOption> COMPRESSION_OPTIONS =
             Collections.unmodifiableSet(EnumSet.of(KexProposalOption.C2SCOMP, KexProposalOption.S2CCOMP));
 
-    private final CompressionFactory factory;
-    private SshServer sshd;
+    private static SshServer sshd;
+    private static int port;
 
+    private final CompressionFactory factory;
+    private final SessionListener listener;
     public CompressionTest(CompressionFactory factory) {
         this.factory = factory;
+        listener = new SessionListener() {
+            @Override
+            @SuppressWarnings("synthetic-access")
+            public void sessionEvent(Session session, Event event) {
+                if (Event.KeyEstablished.equals(event)) {
+                    String expected = factory.getName();
+                    for (KexProposalOption option : COMPRESSION_OPTIONS) {
+                        String actual = session.getNegotiatedKexParameter(KexProposalOption.C2SCOMP);
+                        assertEquals("Mismatched value for " + option, expected, actual);
+                    }
+                }
+            }
+        };
     }
 
     @Parameters(name = "factory={0}")
@@ -73,28 +91,30 @@ public class CompressionTest extends BaseTestSupport {
     }
 
     @BeforeClass
-    public static void jschInit() {
+    public static void setupClientAndServer() throws Exception {
         JSchLogger.init();
+
+        sshd = Utils.setupTestServer(MacTest.class);
+        sshd.setKeyPairProvider(Utils.createTestHostKeyProvider(MacTest.class));
+        sshd.start();
+        port = sshd.getPort();
+    }
+
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
+        if (sshd != null) {
+            try {
+                sshd.stop(true);
+            } finally {
+                sshd = null;
+            }
+        }
     }
 
     @Before
     public void setUp() throws Exception {
-        sshd = setupTestServer();
         sshd.setCompressionFactories(Arrays.<NamedFactory<org.apache.sshd.common.compression.Compression>>asList(factory));
-        sshd.addSessionListener(new SessionListener() {
-            @Override
-            @SuppressWarnings("synthetic-access")
-            public void sessionEvent(Session session, Event event) {
-                if (Event.KeyEstablished.equals(event)) {
-                    String expected = factory.getName();
-                    for (KexProposalOption option : COMPRESSION_OPTIONS) {
-                        String actual = session.getNegotiatedKexParameter(KexProposalOption.C2SCOMP);
-                        assertEquals("Mismatched value for " + option, expected, actual);
-                    }
-                }
-            }
-        });
-        sshd.start();
+        sshd.addSessionListener(listener);
 
         String name = factory.getName();
         JSch.setConfig("compression.s2c", name);
@@ -106,7 +126,7 @@ public class CompressionTest extends BaseTestSupport {
     @After
     public void tearDown() throws Exception {
         if (sshd != null) {
-            sshd.stop(true);
+            sshd.removeSessionListener(listener);
         }
         JSch.setConfig("compression.s2c", "none");
         JSch.setConfig("compression.c2s", "none");
@@ -117,7 +137,7 @@ public class CompressionTest extends BaseTestSupport {
         Assume.assumeTrue("Skip unsupported compression " + factory, factory.isSupported());
 
         JSch sch = new JSch();
-        com.jcraft.jsch.Session s = sch.getSession(getCurrentTestName(), TEST_LOCALHOST, sshd.getPort());
+        com.jcraft.jsch.Session s = sch.getSession(getCurrentTestName(), TEST_LOCALHOST, port);
         s.setUserInfo(new SimpleUserInfo(getCurrentTestName()));
 
         s.connect();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/forward/PortForwardingLoadTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/forward/PortForwardingLoadTest.java b/sshd-core/src/test/java/org/apache/sshd/common/forward/PortForwardingLoadTest.java
index 86786a4..c788596 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/forward/PortForwardingLoadTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/forward/PortForwardingLoadTest.java
@@ -127,6 +127,7 @@ public class PortForwardingLoadTest extends BaseTestSupport {
             log.info("tornDownDynamicTunnel(session={}, address={}, reason={})", session, address, reason);
         }
     };
+
     private SshServer sshd;
     private int sshPort;
     private IoAcceptor acceptor;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/forward/PortForwardingTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/forward/PortForwardingTest.java b/sshd-core/src/test/java/org/apache/sshd/common/forward/PortForwardingTest.java
index 8aae6e2..cba1951 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/forward/PortForwardingTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/forward/PortForwardingTest.java
@@ -66,12 +66,12 @@ import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.JSchLogger;
 import org.apache.sshd.util.test.SimpleUserInfo;
 import org.apache.sshd.util.test.Utils;
-import org.junit.After;
-import org.junit.Before;
+import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
+import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
@@ -79,10 +79,9 @@ import org.slf4j.LoggerFactory;
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class PortForwardingTest extends BaseTestSupport {
-
-    private final org.slf4j.Logger log = LoggerFactory.getLogger(getClass());
     @SuppressWarnings("checkstyle:anoninnerlength")
-    private final PortForwardingEventListener serverSideListener = new PortForwardingEventListener() {
+    private static final PortForwardingEventListener SERVER_SIDE_LISTENER = new PortForwardingEventListener() {
+        private final org.slf4j.Logger log = LoggerFactory.getLogger(PortForwardingEventListener.class);
 
         @Override
         public void establishingExplicitTunnel(org.apache.sshd.common.session.Session session, SshdSocketAddress local,
@@ -137,34 +136,31 @@ public class PortForwardingTest extends BaseTestSupport {
         }
     };
 
-    private final BlockingQueue<String> requestsQ = new LinkedBlockingDeque<>();
-
-    private SshServer sshd;
-    private int sshPort;
-    private int echoPort;
-    private IoAcceptor acceptor;
-    private SshClient client;
+    private static final BlockingQueue<String> REQUESTS_QUEUE = new LinkedBlockingDeque<>();
+    private static SshServer sshd;
+    private static int sshPort;
+    private static int echoPort;
+    private static IoAcceptor acceptor;
+    private static SshClient client;
 
+    private final Logger log = LoggerFactory.getLogger(getClass());
     public PortForwardingTest() {
         super();
     }
 
     @BeforeClass
-    public static void jschInit() {
+    public static void setUpTestEnvironment() throws Exception {
         JSchLogger.init();
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        sshd = setupTestServer();
+        sshd = Utils.setupTestServer(PortForwardingTest.class);
         PropertyResolverUtils.updateProperty(sshd, FactoryManager.WINDOW_SIZE, 2048);
         PropertyResolverUtils.updateProperty(sshd, FactoryManager.MAX_PACKET_SIZE, 256);
         sshd.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
-        sshd.addPortForwardingEventListener(serverSideListener);
+        sshd.addPortForwardingEventListener(SERVER_SIDE_LISTENER);
         sshd.start();
+        sshPort = sshd.getPort();
 
-        if (!requestsQ.isEmpty()) {
-            requestsQ.clear();
+        if (!REQUESTS_QUEUE.isEmpty()) {
+            REQUESTS_QUEUE.clear();
         }
 
         final TcpipForwarderFactory factory = ValidateUtils.checkNotNull(sshd.getTcpipForwarderFactory(), "No TcpipForwarderFactory");
@@ -186,6 +182,8 @@ public class PortForwardingTest extends BaseTestSupport {
 
                 final TcpipForwarder forwarder = factory.create(service);
                 return (TcpipForwarder) Proxy.newProxyInstance(cl, interfaces, new InvocationHandler() {
+                    private final org.slf4j.Logger log = LoggerFactory.getLogger(TcpipForwarder.class);
+
                     @SuppressWarnings("synthetic-access")
                     @Override
                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
@@ -193,7 +191,7 @@ public class PortForwardingTest extends BaseTestSupport {
                         String name = method.getName();
                         String request = method2req.get(name);
                         if (GenericUtils.length(request) > 0) {
-                            if (requestsQ.offer(request)) {
+                            if (REQUESTS_QUEUE.offer(request)) {
                                 log.info("Signal " + request);
                             } else {
                                 log.error("Failed to offer request=" + request);
@@ -204,7 +202,6 @@ public class PortForwardingTest extends BaseTestSupport {
                 });
             }
         });
-        sshPort = sshd.getPort();
 
         NioSocketAcceptor acceptor = new NioSocketAcceptor();
         acceptor.setHandler(new IoHandlerAdapter() {
@@ -220,13 +217,28 @@ public class PortForwardingTest extends BaseTestSupport {
         acceptor.setReuseAddress(true);
         acceptor.bind(new InetSocketAddress(0));
         echoPort = acceptor.getLocalAddress().getPort();
-        this.acceptor = acceptor;
+
+        client = Utils.setupTestClient(PortForwardingTest.class);
+        client.start();
+    }
+
+    @AfterClass
+    public static void tearDownTestEnvironment() throws Exception {
+        if (sshd != null) {
+            sshd.stop(true);
+        }
+        if (acceptor != null) {
+            acceptor.dispose(true);
+        }
+        if (client != null) {
+            client.stop();
+        }
     }
 
     private void waitForForwardingRequest(String expected, long timeout) throws InterruptedException {
         for (long remaining = timeout; remaining > 0L;) {
             long waitStart = System.currentTimeMillis();
-            String actual = requestsQ.poll(remaining, TimeUnit.MILLISECONDS);
+            String actual = REQUESTS_QUEUE.poll(remaining, TimeUnit.MILLISECONDS);
             long waitEnd = System.currentTimeMillis();
             if (GenericUtils.isEmpty(actual)) {
                 throw new IllegalStateException("Failed to retrieve request=" + expected);
@@ -243,19 +255,6 @@ public class PortForwardingTest extends BaseTestSupport {
         throw new IllegalStateException("Timeout while waiting to retrieve request=" + expected);
     }
 
-    @After
-    public void tearDown() throws Exception {
-        if (sshd != null) {
-            sshd.stop(true);
-        }
-        if (acceptor != null) {
-            acceptor.dispose(true);
-        }
-        if (client != null) {
-            client.stop();
-        }
-    }
-
     @Test
     public void testRemoteForwarding() throws Exception {
         Session session = createSession();
@@ -800,14 +799,12 @@ public class PortForwardingTest extends BaseTestSupport {
     }
 
     protected ClientSession createNativeSession(PortForwardingEventListener listener) throws Exception {
-        client = setupTestClient();
         PropertyResolverUtils.updateProperty(client, FactoryManager.WINDOW_SIZE, 2048);
         PropertyResolverUtils.updateProperty(client, FactoryManager.MAX_PACKET_SIZE, 256);
         client.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
         if (listener != null) {
             client.addPortForwardingEventListener(listener);
         }
-        client.start();
 
         ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, sshPort).verify(7L, TimeUnit.SECONDS).getSession();
         session.addPasswordIdentity(getCurrentTestName());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/kex/KexFactoryManagerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/kex/KexFactoryManagerTest.java b/sshd-core/src/test/java/org/apache/sshd/common/kex/KexFactoryManagerTest.java
index ed2f9e3..b2a9682 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/kex/KexFactoryManagerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/kex/KexFactoryManagerTest.java
@@ -49,7 +49,7 @@ public class KexFactoryManagerTest extends BaseTestSupport {
 
     @Test
     public void testDefaultCompressionFactoriesMethods() {
-        KexFactoryManager manager =  new TestKexFactoryManager();
+        KexFactoryManager manager = new TestKexFactoryManager();
         assertEquals("Mismatched empty factories name list", "", manager.getCompressionFactoriesNameList());
 
         String expected = NamedResource.Utils.getNames(BuiltinCompressions.VALUES);
@@ -66,7 +66,7 @@ public class KexFactoryManagerTest extends BaseTestSupport {
 
     @Test
     public void testDefaultCipherFactoriesMethods() {
-        KexFactoryManager manager =  new TestKexFactoryManager();
+        KexFactoryManager manager = new TestKexFactoryManager();
         assertEquals("Mismatched empty factories name list", "", manager.getCipherFactoriesNameList());
 
         String expected = NamedResource.Utils.getNames(BuiltinCiphers.VALUES);
@@ -83,7 +83,7 @@ public class KexFactoryManagerTest extends BaseTestSupport {
 
     @Test
     public void testDefaultMacFactoriesMethods() {
-        KexFactoryManager manager =  new TestKexFactoryManager();
+        KexFactoryManager manager = new TestKexFactoryManager();
         assertEquals("Mismatched empty factories name list", "", manager.getMacFactoriesNameList());
 
         String expected = NamedResource.Utils.getNames(BuiltinMacs.VALUES);
@@ -100,7 +100,7 @@ public class KexFactoryManagerTest extends BaseTestSupport {
 
     @Test
     public void testDefaultSignatureFactoriesMethods() {
-        KexFactoryManager manager =  new TestKexFactoryManager();
+        KexFactoryManager manager = new TestKexFactoryManager();
         assertEquals("Mismatched empty factories name list", "", manager.getSignatureFactoriesNameList());
 
         String expected = NamedResource.Utils.getNames(BuiltinSignatures.VALUES);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/mac/MacTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/mac/MacTest.java b/sshd-core/src/test/java/org/apache/sshd/common/mac/MacTest.java
index 89081ae..20e5c69 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/mac/MacTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/mac/MacTest.java
@@ -39,7 +39,8 @@ import org.apache.sshd.server.SshServer;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.JSchLogger;
 import org.apache.sshd.util.test.SimpleUserInfo;
-import org.junit.After;
+import org.apache.sshd.util.test.Utils;
+import org.junit.AfterClass;
 import org.junit.Assume;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -75,10 +76,11 @@ public class MacTest extends BaseTestSupport {
                 }
             });
 
+    private static SshServer sshd;
+    private static int port;
+
     private final MacFactory factory;
     private final String jschMacClass;
-    private SshServer sshd;
-    private int port;
 
     public MacTest(MacFactory factory, String jschMacClass) {
         this.factory = factory;
@@ -119,27 +121,33 @@ public class MacTest extends BaseTestSupport {
         return ret;
     }
 
+
     @BeforeClass
-    public static void jschnit() {
+    public static void setupClientAndServer() throws Exception {
         JSchLogger.init();
-    }
 
-    @Before
-    public void setUp() throws Exception {
-        sshd = setupTestServer();
-        sshd.setKeyPairProvider(createTestHostKeyProvider());
-        sshd.setMacFactories(Arrays.<NamedFactory<Mac>>asList(factory));
+        sshd = Utils.setupTestServer(MacTest.class);
+        sshd.setKeyPairProvider(Utils.createTestHostKeyProvider(MacTest.class));
         sshd.start();
         port = sshd.getPort();
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
         if (sshd != null) {
-            sshd.stop(true);
+            try {
+                sshd.stop(true);
+            } finally {
+                sshd = null;
+            }
         }
     }
 
+    @Before
+    public void setUp() throws Exception {
+        sshd.setMacFactories(Arrays.<NamedFactory<Mac>>asList(factory));
+    }
+
     @Test
     public void testWithJSCH() throws Exception {
         String macName = factory.getName();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/signature/AbstractSignatureFactoryTestSupport.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/AbstractSignatureFactoryTestSupport.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/AbstractSignatureFactoryTestSupport.java
deleted file mode 100644
index 0979a6c..0000000
--- a/sshd-core/src/test/java/org/apache/sshd/common/signature/AbstractSignatureFactoryTestSupport.java
+++ /dev/null
@@ -1,130 +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.sshd.common.signature;
-
-import java.security.KeyPair;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.sshd.client.SshClient;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.common.Factory;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.RuntimeSshException;
-import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder;
-import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.server.SshServer;
-import org.apache.sshd.util.test.BaseTestSupport;
-import org.junit.After;
-import org.junit.Before;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public abstract class AbstractSignatureFactoryTestSupport extends BaseTestSupport {
-    private SshServer sshd;
-    private SshClient client;
-    private int port;
-
-    private final String keyType;
-    private final int keySize;
-
-    protected AbstractSignatureFactoryTestSupport(String keyType, int keySize) {
-        this.keyType = ValidateUtils.checkNotNullAndNotEmpty(keyType, "No key type specified");
-        ValidateUtils.checkTrue(keySize > 0, "Invalid key size: %d", keySize);
-        this.keySize = keySize;
-    }
-
-    public final int getKeySize() {
-        return keySize;
-    }
-
-    public final String getKeyType() {
-        return keyType;
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        sshd = setupTestServer();
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        if (sshd != null) {
-            sshd.stop(true);
-        }
-        if (client != null) {
-            client.stop();
-        }
-    }
-
-    protected void testKeyPairProvider(PublicKeyEntryDecoder<?, ?> decoder, List<NamedFactory<Signature>> signatures) throws Exception {
-        testKeyPairProvider(getKeyType(), getKeySize(), decoder, signatures);
-    }
-
-    protected void testKeyPairProvider(
-            final String keyName, final int keySize, final PublicKeyEntryDecoder<?, ?> decoder, List<NamedFactory<Signature>> signatures)
-            throws Exception {
-        testKeyPairProvider(keyName, new Factory<Iterable<KeyPair>>() {
-            @Override
-            public Iterable<KeyPair> create() {
-                try {
-                    KeyPair kp = decoder.generateKeyPair(keySize);
-                    outputDebugMessage("Generated key pair for %s - key size=%d", keyName, keySize);
-                    return Collections.singletonList(kp);
-                } catch (Exception e) {
-                    throw new RuntimeSshException(e);
-                }
-            }
-        }, signatures);
-    }
-
-    protected void testKeyPairProvider(
-            final String keyName, final Factory<Iterable<KeyPair>> factory, List<NamedFactory<Signature>> signatures)
-            throws Exception {
-        final Iterable<KeyPair> iter = factory.create();
-        testKeyPairProvider(new AbstractKeyPairProvider() {
-            @Override
-            public Iterable<KeyPair> loadKeys() {
-                return iter;
-            }
-        }, signatures);
-    }
-
-    protected void testKeyPairProvider(KeyPairProvider provider, List<NamedFactory<Signature>> signatures) throws Exception {
-        sshd.setKeyPairProvider(provider);
-        sshd.start();
-        port = sshd.getPort();
-
-        client = setupTestClient();
-        client.setSignatureFactories(signatures);
-        client.start();
-        try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-            s.addPasswordIdentity(getCurrentTestName());
-            // allow a rather long timeout since generating some keys may take some time
-            s.auth().verify(30L, TimeUnit.SECONDS);
-        } finally {
-            client.stop();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureDSSFactoryTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureDSSFactoryTest.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureDSSFactoryTest.java
deleted file mode 100644
index 949dcd4..0000000
--- a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureDSSFactoryTest.java
+++ /dev/null
@@ -1,58 +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.sshd.common.signature;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.config.keys.DSSPublicKeyEntryDecoder;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.junit.FixMethodOrder;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.MethodSorters;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
-public class SignatureDSSFactoryTest extends AbstractSignatureFactoryTestSupport {
-    private static final List<NamedFactory<Signature>> FACTORIES =
-            Collections.unmodifiableList(Collections.<NamedFactory<Signature>>singletonList(BuiltinSignatures.dsa));
-
-    public SignatureDSSFactoryTest(int keySize) {
-        super(KeyPairProvider.SSH_DSS, keySize);
-    }
-
-    @Parameters(name = "keySize={0}")
-    public static Collection<Object[]> parameters() {
-        return parameterize(DSS_SIZES);
-    }
-
-    @Test
-    public void testDSSPublicKeyAuth() throws Exception {
-        testKeyPairProvider(DSSPublicKeyEntryDecoder.INSTANCE, FACTORIES);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureECDSAFactoryTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureECDSAFactoryTest.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureECDSAFactoryTest.java
deleted file mode 100644
index 5958f40..0000000
--- a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureECDSAFactoryTest.java
+++ /dev/null
@@ -1,68 +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.sshd.common.signature;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.cipher.ECCurves;
-import org.apache.sshd.common.config.keys.ECDSAPublicKeyEntryDecoder;
-import org.apache.sshd.common.util.SecurityUtils;
-import org.junit.Assume;
-import org.junit.FixMethodOrder;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.MethodSorters;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-/**
- * Makes sure that all the available {@link Signature} implementations are tested
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
-public class SignatureECDSAFactoryTest extends AbstractSignatureFactoryTestSupport {
-    private static final List<NamedFactory<Signature>> FACTORIES =
-            Collections.unmodifiableList(
-                    Arrays.<NamedFactory<Signature>>asList(
-                            BuiltinSignatures.nistp256,
-                            BuiltinSignatures.nistp384,
-                            BuiltinSignatures.nistp521
-                    ));
-
-    public SignatureECDSAFactoryTest(ECCurves curve) {
-        super(curve.getName(), curve.getKeySize());
-    }
-
-    @Parameters(name = "keySize={0}")
-    public static Collection<Object[]> parameters() {
-        return parameterize(ECCurves.VALUES);
-    }
-
-    @Test
-    public void testECDSAPublicKeyAuth() throws Exception {
-        Assume.assumeTrue("ECC not supported", SecurityUtils.hasEcc());
-        testKeyPairProvider(ECDSAPublicKeyEntryDecoder.INSTANCE, FACTORIES);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java
new file mode 100644
index 0000000..4896c5e
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.sshd.common.signature;
+
+import java.security.KeyPair;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.common.Factory;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.RuntimeSshException;
+import org.apache.sshd.common.cipher.ECCurves;
+import org.apache.sshd.common.config.keys.DSSPublicKeyEntryDecoder;
+import org.apache.sshd.common.config.keys.ECDSAPublicKeyEntryDecoder;
+import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder;
+import org.apache.sshd.common.config.keys.RSAPublicKeyDecoder;
+import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.server.SshServer;
+import org.apache.sshd.util.test.BaseTestSupport;
+import org.apache.sshd.util.test.Utils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+public class SignatureFactoriesTest extends BaseTestSupport {
+    private static SshServer sshd;
+    private static SshClient client;
+    private static int port;
+
+    private final String keyType;
+    private final int keySize;
+    private final NamedFactory<Signature> factory;
+    private final PublicKeyEntryDecoder<?, ?> pubKeyDecoder;
+
+    public SignatureFactoriesTest(String keyType, NamedFactory<Signature> factory, int keySize, PublicKeyEntryDecoder<?, ?> decoder) {
+        this.keyType = ValidateUtils.checkNotNullAndNotEmpty(keyType, "No key type specified");
+        this.factory = Objects.requireNonNull(factory, "No signature factory provided");
+        ValidateUtils.checkTrue(keySize > 0, "Invalid key size: %d", keySize);
+        this.keySize = keySize;
+        this.pubKeyDecoder = Objects.requireNonNull(decoder, "No public key decoder provided");
+    }
+
+    @Parameters(name = "type={0}, size={2}")
+    public static List<Object[]> parameters() {
+        return Collections.unmodifiableList(new ArrayList<Object[]>() {
+            // Not serializing it
+            private static final long serialVersionUID = 1L;
+
+            {
+                addTests(KeyPairProvider.SSH_DSS, BuiltinSignatures.dsa, DSS_SIZES, DSSPublicKeyEntryDecoder.INSTANCE);
+                addTests(KeyPairProvider.SSH_RSA, BuiltinSignatures.rsa, RSA_SIZES, RSAPublicKeyDecoder.INSTANCE);
+                if (SecurityUtils.hasEcc()) {
+                    for (ECCurves curve : ECCurves.VALUES) {
+                        BuiltinSignatures factory = BuiltinSignatures.fromFactoryName(curve.getKeyType());
+                        addTests(curve.getName(), factory, Collections.singletonList(curve.getKeySize()), ECDSAPublicKeyEntryDecoder.INSTANCE);
+                    }
+                }
+            }
+
+            private void addTests(String keyType, NamedFactory<Signature> factory, Collection<Integer> sizes, PublicKeyEntryDecoder<?, ?> decoder) {
+                for (Integer keySize : sizes) {
+                    add(new Object[]{keyType, factory, keySize, decoder});
+                }
+            }
+        });
+    }
+
+    @BeforeClass
+    public static void setupClientAndServer() throws Exception {
+        sshd = Utils.setupTestServer(SignatureFactoriesTest.class);
+        sshd.start();
+        port = sshd.getPort();
+
+        client = Utils.setupTestClient(SignatureFactoriesTest.class);
+        client.start();
+    }
+
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
+        if (sshd != null) {
+            try {
+                sshd.stop(true);
+            } finally {
+                sshd = null;
+            }
+        }
+
+        if (client != null) {
+            try {
+                client.stop();
+            } finally {
+                client = null;
+            }
+        }
+    }
+
+    public final int getKeySize() {
+        return keySize;
+    }
+
+    public final String getKeyType() {
+        return keyType;
+    }
+
+    @Test
+    public void testPublicKeyAuth() throws Exception {
+        testKeyPairProvider(getKeyType(), getKeySize(), pubKeyDecoder, Collections.singletonList(factory));
+    }
+
+    protected void testKeyPairProvider(
+            final String keyName, final int keySize, final PublicKeyEntryDecoder<?, ?> decoder, List<NamedFactory<Signature>> signatures)
+                    throws Exception {
+        testKeyPairProvider(keyName, new Factory<Iterable<KeyPair>>() {
+            @Override
+            public Iterable<KeyPair> create() {
+                try {
+                    KeyPair kp = decoder.generateKeyPair(keySize);
+                    outputDebugMessage("Generated key pair for %s - key size=%d", keyName, keySize);
+                    return Collections.singletonList(kp);
+                } catch (Exception e) {
+                    throw new RuntimeSshException(e);
+                }
+            }
+        }, signatures);
+    }
+
+    protected void testKeyPairProvider(
+            final String keyName, final Factory<Iterable<KeyPair>> keyPairFactory, List<NamedFactory<Signature>> signatures)
+                    throws Exception {
+        final Iterable<KeyPair> iter = keyPairFactory.create();
+        testKeyPairProvider(new AbstractKeyPairProvider() {
+            @Override
+            public Iterable<KeyPair> loadKeys() {
+                return iter;
+            }
+        }, signatures);
+    }
+
+    protected void testKeyPairProvider(KeyPairProvider provider, List<NamedFactory<Signature>> signatures) throws Exception {
+        sshd.setKeyPairProvider(provider);
+        client.setSignatureFactories(signatures);
+        try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            s.addPasswordIdentity(getCurrentTestName());
+            // allow a rather long timeout since generating some keys may take some time
+            s.auth().verify(30L, TimeUnit.SECONDS);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureRSAFactoryTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureRSAFactoryTest.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureRSAFactoryTest.java
deleted file mode 100644
index 33960ce..0000000
--- a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureRSAFactoryTest.java
+++ /dev/null
@@ -1,58 +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.sshd.common.signature;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.config.keys.RSAPublicKeyDecoder;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.junit.FixMethodOrder;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.MethodSorters;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
-public class SignatureRSAFactoryTest extends AbstractSignatureFactoryTestSupport {
-    private static final List<NamedFactory<Signature>> FACTORIES =
-            Collections.unmodifiableList(Collections.<NamedFactory<Signature>>singletonList(BuiltinSignatures.rsa));
-
-    public SignatureRSAFactoryTest(int keySize) {
-        super(KeyPairProvider.SSH_RSA, keySize);
-    }
-
-    @Parameters(name = "keySize={0}")
-    public static Collection<Object[]> parameters() {
-        return parameterize(RSA_SIZES);
-    }
-
-    @Test
-    public void testRSAPublicKeyAuth() throws Exception {
-        testKeyPairProvider(RSAPublicKeyDecoder.INSTANCE, FACTORIES);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/server/ServerSessionListenerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/ServerSessionListenerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/ServerSessionListenerTest.java
index 4b13e8a..5fcaba2 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/ServerSessionListenerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/ServerSessionListenerTest.java
@@ -47,8 +47,9 @@ import org.apache.sshd.server.auth.password.PasswordAuthenticator;
 import org.apache.sshd.server.auth.password.PasswordChangeRequiredException;
 import org.apache.sshd.server.session.ServerSession;
 import org.apache.sshd.util.test.BaseTestSupport;
-import org.junit.After;
-import org.junit.Before;
+import org.apache.sshd.util.test.Utils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
@@ -60,29 +61,40 @@ import org.slf4j.LoggerFactory;
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class ServerSessionListenerTest extends BaseTestSupport {
-    private SshServer sshd;
-    private SshClient client;
-    private int port;
+    private static SshServer sshd;
+    private static int port;
+    private static SshClient client;
 
     public ServerSessionListenerTest() {
         super();
     }
-    @Before
-    public void setUp() throws Exception {
-        sshd = setupTestServer();
+
+    @BeforeClass
+    public static void setupClientAndServer() throws Exception {
+        sshd = Utils.setupTestServer(ServerSessionListenerTest.class);
         sshd.start();
         port = sshd.getPort();
 
-        client = setupTestClient();
+        client = Utils.setupTestClient(ServerSessionListenerTest.class);
+        client.start();
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
         if (sshd != null) {
-            sshd.stop(true);
+            try {
+                sshd.stop(true);
+            } finally {
+                sshd = null;
+            }
         }
+
         if (client != null) {
-            client.stop();
+            try {
+                client.stop();
+            } finally {
+                client = null;
+            }
         }
     }
 
@@ -90,7 +102,7 @@ public class ServerSessionListenerTest extends BaseTestSupport {
     public void testServerStillListensIfSessionListenerThrowsException() throws Exception {
         final Map<String, SocketAddress> eventsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
         final Logger log = LoggerFactory.getLogger(getClass());
-        sshd.addSessionListener(new SessionListener() {
+        SessionListener listener = new SessionListener() {
             @Override
             public void sessionCreated(Session session) {
                 throwException("SessionCreated", session);
@@ -119,36 +131,38 @@ public class ServerSessionListenerTest extends BaseTestSupport {
                 log.info(e.getMessage());
                 throw e;
             }
-        });
-
-        client.start();
+        };
+        sshd.addSessionListener(listener);
 
         int curCount = 0;
-        for (int retryCount = 0; retryCount < Byte.SIZE; retryCount++) {
-            synchronized (eventsMap) {
-                curCount = eventsMap.size();
-                if (curCount >= 3) {
-                    return;
+        try {
+            for (int retryCount = 0; retryCount < Byte.SIZE; retryCount++) {
+                synchronized (eventsMap) {
+                    curCount = eventsMap.size();
+                    if (curCount >= 3) {
+                        return;
+                    }
                 }
-            }
 
-            try {
-                try (ClientSession s = createTestClientSession()) {
-                    log.info("Retry #" + retryCount + " successful");
-                }
+                try {
+                    try (ClientSession s = createTestClientSession()) {
+                        log.info("Retry #" + retryCount + " successful");
+                    }
 
-                synchronized (eventsMap) {
-                    assertTrue("Unexpected premature success at retry # " + retryCount + ": " + eventsMap, eventsMap.size() >= 3);
-                }
-            } catch (IOException e) {
-                // expected - ignored
-                synchronized (eventsMap) {
-                    int nextCount = eventsMap.size();
-                    assertTrue("No session event generated at retry #" + retryCount, nextCount > curCount);
+                    synchronized (eventsMap) {
+                        assertTrue("Unexpected premature success at retry # " + retryCount + ": " + eventsMap, eventsMap.size() >= 3);
+                    }
+                } catch (IOException e) {
+                    // expected - ignored
+                    synchronized (eventsMap) {
+                        int nextCount = eventsMap.size();
+                        assertTrue("No session event generated at retry #" + retryCount, nextCount > curCount);
+                    }
                 }
             }
+        } finally {
+            sshd.removeSessionListener(listener);
         }
-
         fail("No success to authenticate");
     }
 
@@ -159,7 +173,7 @@ public class ServerSessionListenerTest extends BaseTestSupport {
         kexParams.put(KexProposalOption.S2CENC, getLeastFavorite(Cipher.class, sshd.getCipherFactories()));
         kexParams.put(KexProposalOption.S2CMAC, getLeastFavorite(Mac.class, sshd.getMacFactories()));
 
-        sshd.addSessionListener(new SessionListener() {
+        SessionListener listener = new SessionListener() {
             @Override
             @SuppressWarnings("unchecked")
             public void sessionCreated(Session session) {
@@ -167,9 +181,9 @@ public class ServerSessionListenerTest extends BaseTestSupport {
                 session.setCipherFactories(Collections.singletonList((NamedFactory<Cipher>) kexParams.get(KexProposalOption.S2CENC)));
                 session.setMacFactories(Collections.singletonList((NamedFactory<Mac>) kexParams.get(KexProposalOption.S2CMAC)));
             }
-        });
+        };
+        sshd.addSessionListener(listener);
 
-        client.start();
         try (ClientSession session = createTestClientSession()) {
             for (Map.Entry<KexProposalOption, ? extends NamedResource> ke : kexParams.entrySet()) {
                 KexProposalOption option = ke.getKey();
@@ -178,7 +192,7 @@ public class ServerSessionListenerTest extends BaseTestSupport {
                 assertEquals("Mismatched values for KEX=" + option, expected, actual);
             }
         } finally {
-            client.stop();
+            sshd.removeSessionListener(listener);
         }
     }
 
@@ -193,7 +207,7 @@ public class ServerSessionListenerTest extends BaseTestSupport {
                 return defaultPassAuth.authenticate(username, password, session);
             }
         };
-        sshd.addSessionListener(new SessionListener() {
+        SessionListener listener = new SessionListener() {
             @Override
             public void sessionCreated(Session session) {
                 if ((!session.isAuthenticated()) && (session instanceof ServerSession)) {
@@ -204,15 +218,15 @@ public class ServerSessionListenerTest extends BaseTestSupport {
                                     ServerAuthenticationManager.Utils.DEFAULT_USER_AUTH_PASSWORD_FACTORY));
                 }
             }
-        });
+        };
+        sshd.addSessionListener(listener);
 
-        client.start();
         try (ClientSession session = createTestClientSession()) {
             assertNotSame("Mismatched default password authenticator", passAuth, sshd.getPasswordAuthenticator());
             assertNotSame("Mismatched default kb authenticator", KeyboardInteractiveAuthenticator.NONE, sshd.getKeyboardInteractiveAuthenticator());
             assertEquals("Authenticator override not invoked", 1, passCount.get());
         } finally {
-            client.stop();
+            sshd.removeSessionListener(listener);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
index 957c0a6..7f75b01 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
@@ -87,8 +87,6 @@ import org.junit.runners.MethodSorters;
 import org.slf4j.LoggerFactory;
 
 /**
- * TODO Add javadoc
- *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/server/auth/WelcomeBannerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/auth/WelcomeBannerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/auth/WelcomeBannerTest.java
index 7f824ad..f54e7f2 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/auth/WelcomeBannerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/auth/WelcomeBannerTest.java
@@ -53,11 +53,11 @@ public class WelcomeBannerTest extends BaseTestSupport {
 
     @BeforeClass
     public static void setupClientAndServer() throws Exception {
-        sshd = Utils.setupTestServer(WelcomeBannerPhaseTest.class);
+        sshd = Utils.setupTestServer(WelcomeBannerTest.class);
         sshd.start();
         port = sshd.getPort();
 
-        client = Utils.setupTestClient(WelcomeBannerPhaseTest.class);
+        client = Utils.setupTestClient(WelcomeBannerTest.class);
         client.start();
     }
 


[4/4] mina-sshd git commit: [SSHD-691] Attempt to create server instance only once per test as much as possible

Posted by lg...@apache.org.
[SSHD-691] Attempt to create server instance only once per test as much as possible


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

Branch: refs/heads/master
Commit: ae8d1c9950c1faf4ffc6ff493aa5650709cd805d
Parents: b5bb002
Author: Lyor Goldstein <ly...@gmail.com>
Authored: Sun Aug 21 18:40:29 2016 +0300
Committer: Lyor Goldstein <ly...@gmail.com>
Committed: Sun Aug 21 18:40:29 2016 +0300

----------------------------------------------------------------------
 .../subsystem/sftp/AbstractSftpClient.java      |   9 +
 .../sshd/client/subsystem/sftp/SftpClient.java  |  10 +
 .../subsystem/sftp/SftpDirEntryIterator.java    |  93 +-
 .../client/subsystem/sftp/SftpFileSystem.java   |   8 +
 .../subsystem/sftp/SftpIterableDirEntry.java    |  14 +-
 .../subsystem/sftp/StfpIterableDirHandle.java   |  59 ++
 .../server/subsystem/sftp/DirectoryHandle.java  |   6 +-
 .../server/subsystem/sftp/SftpSubsystem.java    |   5 +-
 .../java/org/apache/sshd/KeepAliveTest.java     |  61 +-
 .../sshd/client/ClientSessionListenerTest.java  |  54 +-
 .../org/apache/sshd/client/kex/KexTest.java     | 106 ++-
 .../org/apache/sshd/client/scp/ScpTest.java     | 940 +++++++++----------
 .../sshd/client/session/ClientSessionTest.java  |  42 +-
 .../client/simple/SimpleSftpClientTest.java     |   8 +-
 .../sftp/AbstractSftpClientTestSupport.java     |  36 +-
 .../subsystem/sftp/SftpFileSystemTest.java      |  33 +-
 .../sshd/client/subsystem/sftp/SftpTest.java    | 840 ++++++++---------
 .../client/subsystem/sftp/SftpVersionsTest.java | 283 +++---
 .../helpers/AbstractCheckFileExtensionTest.java |  56 +-
 .../helpers/AbstractMD5HashExtensionTest.java   |  70 +-
 .../helpers/CopyDataExtensionImplTest.java      |  52 +-
 .../helpers/CopyFileExtensionImplTest.java      |  43 +-
 .../SpaceAvailableExtensionImplTest.java        |  32 +-
 .../openssh/helpers/OpenSSHExtensionsTest.java  |  40 +-
 .../apache/sshd/common/cipher/CipherTest.java   |  30 +-
 .../common/compression/CompressionTest.java     |  60 +-
 .../common/forward/PortForwardingLoadTest.java  |   1 +
 .../sshd/common/forward/PortForwardingTest.java |  77 +-
 .../sshd/common/kex/KexFactoryManagerTest.java  |   8 +-
 .../org/apache/sshd/common/mac/MacTest.java     |  34 +-
 .../AbstractSignatureFactoryTestSupport.java    | 130 ---
 .../signature/SignatureDSSFactoryTest.java      |  58 --
 .../signature/SignatureECDSAFactoryTest.java    |  68 --
 .../signature/SignatureFactoriesTest.java       | 184 ++++
 .../signature/SignatureRSAFactoryTest.java      |  58 --
 .../sshd/server/ServerSessionListenerTest.java  | 102 +-
 .../java/org/apache/sshd/server/ServerTest.java |   2 -
 .../sshd/server/auth/WelcomeBannerTest.java     |   4 +-
 38 files changed, 1788 insertions(+), 1928 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
index 4284dc2..ecf6ffb 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
@@ -1130,6 +1130,15 @@ public abstract class AbstractSftpClient extends AbstractSubsystemClient impleme
     }
 
     @Override
+    public Iterable<DirEntry> listDir(Handle handle) throws IOException {
+        if (!isOpen()) {
+            throw new IOException("listDir(" + handle + ") client is closed");
+        }
+
+        return new StfpIterableDirHandle(this, handle);
+    }
+
+    @Override
     public InputStream read(final String path, final int bufferSize, final Collection<OpenMode> mode) throws IOException {
         if (bufferSize < MIN_READ_BUFFER_SIZE) {
             throw new IllegalArgumentException("Insufficient read buffer size: " + bufferSize + ", min.=" + MIN_READ_BUFFER_SIZE);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java
index 1673ebb..49d09f8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java
@@ -634,6 +634,16 @@ public interface SftpClient extends SubsystemClient {
     List<DirEntry> readDir(Handle handle, AtomicReference<Boolean> eolIndicator) throws IOException;
 
     /**
+     * @param handle A directory {@link Handle}
+     * @return An {@link Iterable} that can be used to iterate over all the
+     * directory entries (like {@link #readDir(String)}). <B>Note:</B> the
+     * iterable instance is not re-usable - i.e., files can be iterated
+     * only <U>once</U>
+     * @throws IOException If failed to access the directory
+     */
+    Iterable<DirEntry> listDir(Handle handle) throws IOException;
+
+    /**
      * The effective &quot;normalized&quot; remote path
      *
      * @param path The requested path - may be relative, and/or contain

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirEntryIterator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirEntryIterator.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirEntryIterator.java
index c828015..e245589 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirEntryIterator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirEntryIterator.java
@@ -18,14 +18,17 @@
  */
 package org.apache.sshd.client.subsystem.sftp;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.nio.channels.Channel;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
-import org.apache.sshd.client.subsystem.sftp.SftpClient.CloseableHandle;
 import org.apache.sshd.client.subsystem.sftp.SftpClient.DirEntry;
+import org.apache.sshd.client.subsystem.sftp.SftpClient.Handle;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.logging.AbstractLoggingBean;
 
@@ -39,27 +42,50 @@ import org.apache.sshd.common.util.logging.AbstractLoggingBean;
  */
 public class SftpDirEntryIterator extends AbstractLoggingBean implements Iterator<DirEntry>, Channel {
     private final AtomicReference<Boolean> eolIndicator = new AtomicReference<>();
+    private final AtomicBoolean open = new AtomicBoolean(true);
     private final SftpClient client;
     private final String dirPath;
-    private CloseableHandle dirHandle;
+    private final boolean closeOnFinished;
+    private Handle dirHandle;
     private List<DirEntry> dirEntries;
     private int index;
 
     /**
      * @param client The {@link SftpClient} instance to use for the iteration
      * @param path The remote directory path
+     * @throws IOException If failed to gain access to the remote directory patj
      */
-    public SftpDirEntryIterator(SftpClient client, String path) {
-        this.client = ValidateUtils.checkNotNull(client, "No SFTP client instance");
-        this.dirPath = path;
-        this.dirHandle = open(path);
+    public SftpDirEntryIterator(SftpClient client, String path) throws IOException {
+        this(client, path, client.openDir(path), true);
+    }
+
+    /**
+     * @param client The {@link SftpClient} instance to use for the iteration
+     * @param dirHandle The directory {@link Handle} to use for listing the entries
+     */
+    public SftpDirEntryIterator(SftpClient client, Handle dirHandle) {
+        this(client, Objects.toString(dirHandle, null), dirHandle, false);
+    }
+
+    /**
+     * @param client The {@link SftpClient} instance to use for the iteration
+     * @param path A hint as to the remote directory path - used only for logging
+     * @param dirHandle The directory {@link Handle} to use for listing the entries
+     * @param closeOnFinished If {@code true} then close the directory handle when
+     * all entries have been exahusted
+     */
+    public SftpDirEntryIterator(SftpClient client, String path, Handle dirHandle, boolean closeOnFinished) {
+        this.client = Objects.requireNonNull(client, "No SFTP client instance");
+        this.dirPath = ValidateUtils.checkNotNullAndNotEmpty(path, "No path");
+        this.dirHandle = Objects.requireNonNull(dirHandle, "No directory handle");
+        this.closeOnFinished = closeOnFinished;
         this.dirEntries = load(dirHandle);
     }
 
     /**
      * The client instance
      *
-     * @return {@link SftpClient} instance used to access the remote file
+     * @return {@link SftpClient} instance used to access the remote folder
      */
     public final SftpClient getClient() {
         return client;
@@ -68,12 +94,20 @@ public class SftpDirEntryIterator extends AbstractLoggingBean implements Iterato
     /**
      * The remotely accessed directory path
      *
-     * @return Remote directory path
+     * @return Remote directory hint - may be the handle's value if accessed directly
+     * via a {@link Handle} instead of via a path - used only for logging
      */
     public final String getPath() {
         return dirPath;
     }
 
+    /**
+     * @return The directory {@link Handle} used to access the remote directory
+     */
+    public final Handle getHandle() {
+        return dirHandle;
+    }
+
     @Override
     public boolean hasNext() {
         return (dirEntries != null) && (index < dirEntries.size());
@@ -86,7 +120,7 @@ public class SftpDirEntryIterator extends AbstractLoggingBean implements Iterato
             index = 0;
 
             try {
-                dirEntries = load(dirHandle);
+                dirEntries = load(getHandle());
             } catch (RuntimeException e) {
                 dirEntries = null;
                 throw e;
@@ -98,42 +132,33 @@ public class SftpDirEntryIterator extends AbstractLoggingBean implements Iterato
 
     @Override
     public boolean isOpen() {
-        return (dirHandle != null) && dirHandle.isOpen();
+        return open.get();
     }
 
-    @Override
-    public void close() throws IOException {
-        if (isOpen()) {
-            if (log.isDebugEnabled()) {
-                log.debug("close(" + getPath() + ") handle=" + dirHandle);
-            }
-            dirHandle.close();
-        }
+    public boolean isCloseOnFinished() {
+        return closeOnFinished;
     }
 
-    protected CloseableHandle open(String path) {
-        try {
-            CloseableHandle handle = client.openDir(path);
-            if (log.isDebugEnabled()) {
-                log.debug("open(" + path + ") handle=" + handle);
-            }
-
-            return handle;
-        } catch (IOException e) {
-            if (log.isDebugEnabled()) {
-                log.debug("open(" + path + ") failed (" + e.getClass().getSimpleName() + ") to open dir: " + e.getMessage());
+    @Override
+    public void close() throws IOException {
+        if (open.getAndSet(false)) {
+            Handle handle = getHandle();
+            if ((handle instanceof Closeable) && isCloseOnFinished()) {
+                if (log.isDebugEnabled()) {
+                    log.debug("close(" + getPath() + ") handle=" + handle);
+                }
+                ((Closeable) handle).close();
             }
-            throw new RuntimeException(e);
         }
     }
 
-    protected List<DirEntry> load(CloseableHandle handle) {
+    protected List<DirEntry> load(Handle handle) {
         try {
             // check if previous call yielded an end-of-list indication
             Boolean eolReached = eolIndicator.getAndSet(null);
             if ((eolReached != null) && eolReached.booleanValue()) {
                 if (log.isTraceEnabled()) {
-                    log.trace("load({}) exhausted all entries on previous call", getPath());
+                    log.trace("load({})[{}] exhausted all entries on previous call", getPath(), handle);
                 }
                 return null;
             }
@@ -142,7 +167,7 @@ public class SftpDirEntryIterator extends AbstractLoggingBean implements Iterato
             eolReached = eolIndicator.get();
             if ((entries == null) || ((eolReached != null) && eolReached.booleanValue())) {
                 if (log.isTraceEnabled()) {
-                    log.trace("load({}) exhausted all entries - EOL={}", getPath(), eolReached);
+                    log.trace("load({})[{}] exhausted all entries - EOL={}", getPath(), handle, eolReached);
                 }
                 close();
             }
@@ -164,6 +189,6 @@ public class SftpDirEntryIterator extends AbstractLoggingBean implements Iterato
 
     @Override
     public void remove() {
-        throw new UnsupportedOperationException("readDir(" + getPath() + ") Iterator#remove() N/A");
+        throw new UnsupportedOperationException("readDir(" + getPath() + ")[" + getHandle() + "] Iterator#remove() N/A");
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
index 11ff32e..4a1bc7a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
@@ -351,6 +351,14 @@ public class SftpFileSystem extends BaseFileSystem<SftpPath> implements ClientSe
         }
 
         @Override
+        public Iterable<DirEntry> listDir(Handle handle) throws IOException {
+            if (!isOpen()) {
+                throw new IOException("readDir(" + handle + ") client is closed");
+            }
+            return delegate.listDir(handle);
+        }
+
+        @Override
         public String canonicalPath(String path) throws IOException {
             if (!isOpen()) {
                 throw new IOException("canonicalPath(" + path + ") client is closed");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpIterableDirEntry.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpIterableDirEntry.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpIterableDirEntry.java
index 890c0cf..945e0d7 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpIterableDirEntry.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpIterableDirEntry.java
@@ -18,7 +18,11 @@
  */
 package org.apache.sshd.client.subsystem.sftp;
 
+import java.io.IOException;
+import java.util.Objects;
+
 import org.apache.sshd.client.subsystem.sftp.SftpClient.DirEntry;
+import org.apache.sshd.common.util.ValidateUtils;
 
 /**
  * Provides an {@link Iterable} implementation of the {@link DirEntry}-ies
@@ -35,8 +39,8 @@ public class SftpIterableDirEntry implements Iterable<DirEntry> {
      * @param path The remote directory path
      */
     public SftpIterableDirEntry(SftpClient client, String path) {
-        this.client = client;
-        this.path = path;
+        this.client = Objects.requireNonNull(client, "No client instance");
+        this.path = ValidateUtils.checkNotNullAndNotEmpty(path, "No remote path");
     }
 
     /**
@@ -59,6 +63,10 @@ public class SftpIterableDirEntry implements Iterable<DirEntry> {
 
     @Override
     public SftpDirEntryIterator iterator() {
-        return new SftpDirEntryIterator(getClient(), getPath());
+        try {
+            return new SftpDirEntryIterator(getClient(), getPath());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/StfpIterableDirHandle.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/StfpIterableDirHandle.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/StfpIterableDirHandle.java
new file mode 100644
index 0000000..c3be157
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/StfpIterableDirHandle.java
@@ -0,0 +1,59 @@
+/*
+ * 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.sshd.client.subsystem.sftp;
+
+import java.util.Objects;
+
+import org.apache.sshd.client.subsystem.sftp.SftpClient.DirEntry;
+import org.apache.sshd.client.subsystem.sftp.SftpClient.Handle;
+
+public class StfpIterableDirHandle implements Iterable<DirEntry> {
+    private final SftpClient client;
+    private final Handle handle;
+
+    /**
+     * @param client The {@link SftpClient} to use for iteration
+     * @param handle The remote directory {@link Handle}
+     */
+    public StfpIterableDirHandle(SftpClient client, Handle handle) {
+        this.client = Objects.requireNonNull(client, "No client instance");
+        this.handle = handle;
+    }
+
+    /**
+     * The client instance
+     *
+     * @return {@link SftpClient} instance used to access the remote file
+     */
+    public final SftpClient getClient() {
+        return client;
+    }
+
+    /**
+     * @return The remote directory {@link Handle}
+     */
+    public final Handle getHandle() {
+        return handle;
+    }
+
+    @Override
+    public SftpDirEntryIterator iterator() {
+        return new SftpDirEntryIterator(getClient(), getHandle());
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/DirectoryHandle.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/DirectoryHandle.java b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/DirectoryHandle.java
index 9a813ce..0319f6a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/DirectoryHandle.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/DirectoryHandle.java
@@ -30,7 +30,7 @@ import java.util.Iterator;
 public class DirectoryHandle extends Handle implements Iterator<Path> {
 
     private boolean done;
-    private boolean sendDotDot;
+    private boolean sendDotDot = true;
     private boolean sendDot = true;
     // the directory should be read once at "open directory"
     private DirectoryStream<Path> ds;
@@ -41,7 +41,9 @@ public class DirectoryHandle extends Handle implements Iterator<Path> {
         ds = Files.newDirectoryStream(file);
 
         Path parent = file.getParent();
-        sendDotDot = parent != null;  // if no parent then no need to send ".."
+        if (parent == null) {
+            sendDotDot = false;  // if no parent then no need to send ".."
+        }
         fileList = ds.iterator();
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index 89cb6f1..4aa4020 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -1838,12 +1838,13 @@ public class SftpSubsystem
                 reply = BufferUtils.clear(buffer);
                 reply.putByte((byte) SftpConstants.SSH_FXP_NAME);
                 reply.putInt(id);
+
                 int lenPos = reply.wpos();
                 reply.putInt(0);
 
-                int count = doReadDir(id, handle, dh, reply, PropertyResolverUtils.getIntProperty(getServerSession(), MAX_PACKET_LENGTH_PROP, DEFAULT_MAX_PACKET_LENGTH));
-                BufferUtils.updateLengthPlaceholder(reply, lenPos, count);
                 ServerSession session = getServerSession();
+                int count = doReadDir(id, handle, dh, reply, PropertyResolverUtils.getIntProperty(session, MAX_PACKET_LENGTH_PROP, DEFAULT_MAX_PACKET_LENGTH));
+                BufferUtils.updateLengthPlaceholder(reply, lenPos, count);
                 if ((!dh.isSendDot()) && (!dh.isSendDotDot()) && (!dh.hasNext())) {
                     dh.markDone();
                 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java b/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
index 03c5375..15cef21 100644
--- a/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
@@ -37,8 +37,11 @@ import org.apache.sshd.server.SshServer;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.EchoShell;
 import org.apache.sshd.util.test.EchoShellFactory;
+import org.apache.sshd.util.test.Utils;
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
@@ -55,34 +58,57 @@ public class KeepAliveTest extends BaseTestSupport {
     private static final long TIMEOUT = 2L * HEARTBEAT;
     private static final long WAIT = 2L * TIMEOUT;
 
-    private SshServer sshd;
-    private int port;
+    private static SshServer sshd;
+    private static int port;
+    private static SshClient client;
 
     public KeepAliveTest() {
         super();
     }
 
-    @Before
-    public void setUp() throws Exception {
-        sshd = setupTestServer();
-        PropertyResolverUtils.updateProperty(sshd, FactoryManager.IDLE_TIMEOUT, TIMEOUT);
+    @BeforeClass
+    public static void setupClientAndServer() throws Exception {
+        sshd = Utils.setupTestServer(KeepAliveTest.class);
         sshd.setShellFactory(new TestEchoShellFactory());
         sshd.start();
         port = sshd.getPort();
+
+        client = Utils.setupTestClient(KeepAliveTest.class);
+        client.start();
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
         if (sshd != null) {
-            sshd.stop(true);
+            try {
+                sshd.stop(true);
+            } finally {
+                sshd = null;
+            }
         }
+
+        if (client != null) {
+            try {
+                client.stop();
+            } finally {
+                client = null;
+            }
+        }
+    }
+
+    @Before
+    public void setUp() {
+        PropertyResolverUtils.updateProperty(sshd, FactoryManager.IDLE_TIMEOUT, TIMEOUT);
+    }
+
+    @After
+    public void tearDown() {
+        PropertyResolverUtils.updateProperty(sshd, FactoryManager.IDLE_TIMEOUT, FactoryManager.DEFAULT_IDLE_TIMEOUT);
+        PropertyResolverUtils.updateProperty(client, ClientFactoryManager.HEARTBEAT_INTERVAL, ClientFactoryManager.DEFAULT_HEARTBEAT_INTERVAL);
     }
 
     @Test
     public void testIdleClient() throws Exception {
-        SshClient client = setupTestClient();
-        client.start();
-
         try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
             session.addPasswordIdentity(getCurrentTestName());
             session.auth().verify(5L, TimeUnit.SECONDS);
@@ -92,17 +118,12 @@ public class KeepAliveTest extends BaseTestSupport {
                         channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), WAIT);
                 assertTrue("Wrong channel state: " + result, result.containsAll(EnumSet.of(ClientChannelEvent.CLOSED)));
             }
-        } finally {
-            client.stop();
         }
     }
 
     @Test
     public void testClientWithHeartBeat() throws Exception {
-        SshClient client = setupTestClient();
         PropertyResolverUtils.updateProperty(client, ClientFactoryManager.HEARTBEAT_INTERVAL, HEARTBEAT);
-        client.start();
-
         try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
             session.addPasswordIdentity(getCurrentTestName());
             session.auth().verify(5L, TimeUnit.SECONDS);
@@ -112,8 +133,6 @@ public class KeepAliveTest extends BaseTestSupport {
                         channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), WAIT);
                 assertTrue("Wrong channel state: " + result, result.contains(ClientChannelEvent.TIMEOUT));
             }
-        } finally {
-            client.stop();
         }
     }
 
@@ -121,9 +140,6 @@ public class KeepAliveTest extends BaseTestSupport {
     public void testShellClosedOnClientTimeout() throws Exception {
         TestEchoShell.latch = new CountDownLatch(1);
 
-        SshClient client = setupTestClient();
-        client.start();
-
         try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
             session.addPasswordIdentity(getCurrentTestName());
             session.auth().verify(5L, TimeUnit.SECONDS);
@@ -145,7 +161,6 @@ public class KeepAliveTest extends BaseTestSupport {
             }
         } finally {
             TestEchoShell.latch = null;
-            client.stop();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/ClientSessionListenerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/ClientSessionListenerTest.java b/sshd-core/src/test/java/org/apache/sshd/client/ClientSessionListenerTest.java
index a1cd3dc..291099d 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/ClientSessionListenerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/ClientSessionListenerTest.java
@@ -43,8 +43,9 @@ import org.apache.sshd.common.session.SessionListener;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.server.SshServer;
 import org.apache.sshd.util.test.BaseTestSupport;
-import org.junit.After;
-import org.junit.Before;
+import org.apache.sshd.util.test.Utils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
@@ -54,29 +55,40 @@ import org.junit.runners.MethodSorters;
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class ClientSessionListenerTest extends BaseTestSupport {
-    private SshServer sshd;
-    private SshClient client;
-    private int port;
+    private static SshServer sshd;
+    private static int port;
+    private static SshClient client;
 
     public ClientSessionListenerTest() {
         super();
     }
 
-    @Before
-    public void setUp() throws Exception {
-        client = setupTestClient();
-        sshd = setupTestServer();
+    @BeforeClass
+    public static void setupClientAndServer() throws Exception {
+        sshd = Utils.setupTestServer(ClientSessionListenerTest.class);
         sshd.start();
         port = sshd.getPort();
+
+        client = Utils.setupTestClient(ClientSessionListenerTest.class);
+        client.start();
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
         if (sshd != null) {
-            sshd.stop(true);
+            try {
+                sshd.stop(true);
+            } finally {
+                sshd = null;
+            }
         }
+
         if (client != null) {
-            client.stop();
+            try {
+                client.stop();
+            } finally {
+                client = null;
+            }
         }
     }
 
@@ -87,7 +99,7 @@ public class ClientSessionListenerTest extends BaseTestSupport {
         kexParams.put(KexProposalOption.C2SENC, getLeastFavorite(Cipher.class, client.getCipherFactories()));
         kexParams.put(KexProposalOption.C2SMAC, getLeastFavorite(Mac.class, client.getMacFactories()));
 
-        client.addSessionListener(new SessionListener() {
+        SessionListener listener = new SessionListener() {
             @Override
             @SuppressWarnings("unchecked")
             public void sessionCreated(Session session) {
@@ -95,9 +107,9 @@ public class ClientSessionListenerTest extends BaseTestSupport {
                 session.setCipherFactories(Collections.singletonList((NamedFactory<Cipher>) kexParams.get(KexProposalOption.C2SENC)));
                 session.setMacFactories(Collections.singletonList((NamedFactory<Mac>) kexParams.get(KexProposalOption.C2SMAC)));
             }
-        });
+        };
+        client.addSessionListener(listener);
 
-        client.start();
         try (ClientSession session = createTestClientSession()) {
             for (Map.Entry<KexProposalOption, ? extends NamedResource> ke : kexParams.entrySet()) {
                 KexProposalOption option = ke.getKey();
@@ -106,7 +118,7 @@ public class ClientSessionListenerTest extends BaseTestSupport {
                 assertEquals("Mismatched values for KEX=" + option, expected, actual);
             }
         } finally {
-            client.stop();
+            client.removeSessionListener(listener);
         }
     }
 
@@ -121,7 +133,7 @@ public class ClientSessionListenerTest extends BaseTestSupport {
             }
         };
 
-        client.addSessionListener(new SessionListener() {
+        SessionListener listener = new SessionListener() {
             @Override
             public void sessionEvent(Session session, Event event) {
                 if ((!session.isAuthenticated()) && (session instanceof ClientSession) && Event.KexCompleted.equals(event)) {
@@ -130,9 +142,9 @@ public class ClientSessionListenerTest extends BaseTestSupport {
                     clientSession.setUserInteraction(UserInteraction.NONE);
                 }
             }
-        });
+        };
+        client.addSessionListener(listener);
 
-        client.start();
         try (ClientSession session = createTestClientSession()) {
             assertNotSame("Invalid default user interaction", UserInteraction.NONE, client.getUserInteraction());
             assertNotSame("Invalid default server key verifier", verifier, client.getServerKeyVerifier());
@@ -140,7 +152,7 @@ public class ClientSessionListenerTest extends BaseTestSupport {
             assertSame("Mismatched session server key verifier", verifier, session.getServerKeyVerifier());
             assertEquals("Mismatched verification count", 1, verificationCount.get());
         } finally {
-            client.stop();
+            client.removeSessionListener(listener);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
index f6ccfbd..291cfce 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
@@ -42,9 +42,10 @@ import org.apache.sshd.common.util.SecurityUtils;
 import org.apache.sshd.server.SshServer;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.TeeOutputStream;
-import org.junit.After;
+import org.apache.sshd.util.test.Utils;
+import org.junit.AfterClass;
 import org.junit.Assume;
-import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -60,10 +61,11 @@ import org.junit.runners.Parameterized.Parameters;
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
 public class KexTest extends BaseTestSupport {
+    private static SshServer sshd;
+    private static int port;
+    private static SshClient client;
 
     private final BuiltinDHFactories factory;
-    private SshServer sshd;
-    private int port;
 
     public KexTest(BuiltinDHFactories factory) {
         this.factory = factory;
@@ -74,17 +76,33 @@ public class KexTest extends BaseTestSupport {
         return parameterize(BuiltinDHFactories.VALUES);
     }
 
-    @Before
-    public void setUp() throws Exception {
-        sshd = setupTestServer();
+
+    @BeforeClass
+    public static void setupClientAndServer() throws Exception {
+        sshd = Utils.setupTestServer(KexTest.class);
         sshd.start();
         port = sshd.getPort();
+
+        client = Utils.setupTestClient(KexTest.class);
+        client.start();
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
         if (sshd != null) {
-            sshd.stop(true);
+            try {
+                sshd.stop(true);
+            } finally {
+                sshd = null;
+            }
+        }
+
+        if (client != null) {
+            try {
+                client.stop();
+            } finally {
+                client = null;
+            }
         }
     }
 
@@ -103,44 +121,38 @@ public class KexTest extends BaseTestSupport {
         try (ByteArrayOutputStream sent = new ByteArrayOutputStream();
              ByteArrayOutputStream out = new ByteArrayOutputStream()) {
 
-            try (SshClient client = setupTestClient()) {
-                client.setKeyExchangeFactories(Collections.singletonList(kex));
-                client.start();
-
-                try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                    session.addPasswordIdentity(getCurrentTestName());
-                    session.auth().verify(5L, TimeUnit.SECONDS);
-
-                    try (ClientChannel channel = session.createChannel(Channel.CHANNEL_SHELL);
-                         PipedOutputStream pipedIn = new PipedOutputStream();
-                         InputStream inPipe = new PipedInputStream(pipedIn);
-                         ByteArrayOutputStream err = new ByteArrayOutputStream();
-                         OutputStream teeOut = new TeeOutputStream(sent, pipedIn)) {
-
-                        channel.setIn(inPipe);
-                        channel.setOut(out);
-                        channel.setErr(err);
-                        channel.open().verify(9L, TimeUnit.SECONDS);
-
-                        teeOut.write("this is my command\n".getBytes(StandardCharsets.UTF_8));
-                        teeOut.flush();
-
-                        StringBuilder sb = new StringBuilder();
-                        for (int i = 0; i < 10; i++) {
-                            sb.append("0123456789");
-                        }
-                        sb.append("\n");
-                        teeOut.write(sb.toString().getBytes(StandardCharsets.UTF_8));
-
-                        teeOut.write("exit\n".getBytes(StandardCharsets.UTF_8));
-                        teeOut.flush();
-
-                        Collection<ClientChannelEvent> result =
-                                channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(15L));
-                        assertFalse("Timeout while waiting for channel closure", result.contains(ClientChannelEvent.TIMEOUT));
+            client.setKeyExchangeFactories(Collections.singletonList(kex));
+            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+                session.addPasswordIdentity(getCurrentTestName());
+                session.auth().verify(5L, TimeUnit.SECONDS);
+
+                try (ClientChannel channel = session.createChannel(Channel.CHANNEL_SHELL);
+                     PipedOutputStream pipedIn = new PipedOutputStream();
+                     InputStream inPipe = new PipedInputStream(pipedIn);
+                     ByteArrayOutputStream err = new ByteArrayOutputStream();
+                     OutputStream teeOut = new TeeOutputStream(sent, pipedIn)) {
+
+                    channel.setIn(inPipe);
+                    channel.setOut(out);
+                    channel.setErr(err);
+                    channel.open().verify(9L, TimeUnit.SECONDS);
+
+                    teeOut.write("this is my command\n".getBytes(StandardCharsets.UTF_8));
+                    teeOut.flush();
+
+                    StringBuilder sb = new StringBuilder();
+                    for (int i = 0; i < 10; i++) {
+                        sb.append("0123456789");
                     }
-                } finally {
-                    client.stop();
+                    sb.append("\n");
+                    teeOut.write(sb.toString().getBytes(StandardCharsets.UTF_8));
+
+                    teeOut.write("exit\n".getBytes(StandardCharsets.UTF_8));
+                    teeOut.flush();
+
+                    Collection<ClientChannelEvent> result =
+                            channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(15L));
+                    assertFalse("Timeout while waiting for channel closure", result.contains(ClientChannelEvent.TIMEOUT));
                 }
             }
 


[3/4] mina-sshd git commit: [SSHD-691] Attempt to create server instance only once per test as much as possible

Posted by lg...@apache.org.
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java b/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
index 5d16071..2ddc21b 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
@@ -69,7 +69,7 @@ import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.JSchLogger;
 import org.apache.sshd.util.test.SimpleUserInfo;
 import org.apache.sshd.util.test.Utils;
-import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
@@ -126,8 +126,9 @@ public class ScpTest extends BaseTestSupport {
         }
     };
 
-    private SshServer sshd;
-    private int port;
+    private static SshServer sshd;
+    private static int port;
+    private static SshClient client;
     private final FileSystemFactory fileSystemFactory;
 
     public ScpTest() throws IOException {
@@ -137,26 +138,41 @@ public class ScpTest extends BaseTestSupport {
     }
 
     @BeforeClass
-    public static void jschInit() {
+    public static void setupClientAndServer() throws Exception {
         JSchLogger.init();
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        sshd = setupTestServer();
+        sshd = Utils.setupTestServer(ScpTest.class);
         sshd.setCommandFactory(new ScpCommandFactory());
-        sshd.setFileSystemFactory(fileSystemFactory);
         sshd.start();
         port = sshd.getPort();
+
+        client = Utils.setupTestClient(ScpTest.class);
+        client.start();
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
         if (sshd != null) {
-            sshd.stop(true);
+            try {
+                sshd.stop(true);
+            } finally {
+                sshd = null;
+            }
+        }
+
+        if (client != null) {
+            try {
+                client.stop();
+            } finally {
+                client = null;
+            }
         }
     }
 
+    @Before
+    public void setUp() throws Exception {
+        sshd.setFileSystemFactory(fileSystemFactory);
+    }
+
     @Test
     public void testNormalizedScpRemotePaths() throws Exception {
         Path targetPath = detectTargetFolder();
@@ -173,40 +189,35 @@ public class ScpTest extends BaseTestSupport {
         String localPath = localFile.toString();
         String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
         String[] remoteComps = GenericUtils.split(remotePath, '/');
+        Factory<? extends Random> factory = client.getRandomFactory();
+        Random rnd = factory.create();
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            ScpClient scp = createScpClient(session);
+            StringBuilder sb = new StringBuilder(remotePath.length() + Long.SIZE);
+            for (int i = 0; i < Math.max(Long.SIZE, remoteComps.length); i++) {
+                if (sb.length() > 0) {
+                    sb.setLength(0);    // start again
+                }
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            Factory<? extends Random> factory = client.getRandomFactory();
-            Random rnd = factory.create();
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                ScpClient scp = createScpClient(session);
-                StringBuilder sb = new StringBuilder(remotePath.length() + Long.SIZE);
-                for (int i = 0; i < Math.max(Long.SIZE, remoteComps.length); i++) {
-                    if (sb.length() > 0) {
-                        sb.setLength(0);    // start again
-                    }
-
-                    sb.append(remoteComps[0]);
-                    for (int j = 1; j < remoteComps.length; j++) {
-                        String name = remoteComps[j];
-                        slashify(sb, rnd);
-                        sb.append(name);
-                    }
+                sb.append(remoteComps[0]);
+                for (int j = 1; j < remoteComps.length; j++) {
+                    String name = remoteComps[j];
                     slashify(sb, rnd);
+                    sb.append(name);
+                }
+                slashify(sb, rnd);
 
-                    String path = sb.toString();
-                    scp.upload(localPath, path);
-                    assertTrue("Remote file not ready for " + path, waitForFile(remoteFile, data.length, TimeUnit.SECONDS.toMillis(5L)));
+                String path = sb.toString();
+                scp.upload(localPath, path);
+                assertTrue("Remote file not ready for " + path, waitForFile(remoteFile, data.length, TimeUnit.SECONDS.toMillis(5L)));
 
-                    byte[] actual = Files.readAllBytes(remoteFile);
-                    assertArrayEquals("Mismatched uploaded data for " + path, data, actual);
-                    Files.delete(remoteFile);
-                    assertFalse("Remote file (" + remoteFile + ") not deleted for " + path, Files.exists(remoteFile));
-                }
+                byte[] actual = Files.readAllBytes(remoteFile);
+                assertArrayEquals("Mismatched uploaded data for " + path, data, actual);
+                Files.delete(remoteFile);
+                assertFalse("Remote file (" + remoteFile + ") not deleted for " + path, Files.exists(remoteFile));
             }
         }
     }
@@ -235,64 +246,51 @@ public class ScpTest extends BaseTestSupport {
         Path remoteFile = remoteDir.resolve(localFile.getFileName().toString());
         String localPath = localFile.toString();
         String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
-
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                ScpClient scp = createScpClient(session);
-                scp.upload(localPath, remotePath);
-                assertFileLength(remoteFile, data.length, TimeUnit.SECONDS.toMillis(5L));
-
-                Path secondRemote = remoteDir.resolve("file-2.txt");
-                String secondPath = Utils.resolveRelativeRemotePath(parentPath, secondRemote);
-                scp.upload(localPath, secondPath);
-                assertFileLength(secondRemote, data.length, TimeUnit.SECONDS.toMillis(5L));
-
-                Path pathRemote = remoteDir.resolve("file-path.txt");
-                String pathPath = Utils.resolveRelativeRemotePath(parentPath, pathRemote);
-                scp.upload(localFile, pathPath);
-                assertFileLength(pathRemote, data.length, TimeUnit.SECONDS.toMillis(5L));
-            } finally {
-                client.stop();
-            }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            ScpClient scp = createScpClient(session);
+            scp.upload(localPath, remotePath);
+            assertFileLength(remoteFile, data.length, TimeUnit.SECONDS.toMillis(5L));
+
+            Path secondRemote = remoteDir.resolve("file-2.txt");
+            String secondPath = Utils.resolveRelativeRemotePath(parentPath, secondRemote);
+            scp.upload(localPath, secondPath);
+            assertFileLength(secondRemote, data.length, TimeUnit.SECONDS.toMillis(5L));
+
+            Path pathRemote = remoteDir.resolve("file-path.txt");
+            String pathPath = Utils.resolveRelativeRemotePath(parentPath, pathRemote);
+            scp.upload(localFile, pathPath);
+            assertFileLength(pathRemote, data.length, TimeUnit.SECONDS.toMillis(5L));
         }
     }
 
     @Test
     public void testScpUploadOverwrite() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+            ScpClient scp = createScpClient(session);
+            String data = getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL;
 
-                ScpClient scp = createScpClient(session);
-                String data = getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL;
+            Path targetPath = detectTargetFolder();
+            Path parentPath = targetPath.getParent();
+            Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
+            Utils.deleteRecursive(scpRoot);
 
-                Path targetPath = detectTargetFolder();
-                Path parentPath = targetPath.getParent();
-                Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
-                Utils.deleteRecursive(scpRoot);
+            Path localDir = assertHierarchyTargetFolderExists(scpRoot.resolve("local"));
+            Path localFile = localDir.resolve("file.txt");
+            Utils.writeFile(localFile, data);
 
-                Path localDir = assertHierarchyTargetFolderExists(scpRoot.resolve("local"));
-                Path localFile = localDir.resolve("file.txt");
-                Utils.writeFile(localFile, data);
+            Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
+            Path remoteFile = remoteDir.resolve(localFile.getFileName());
+            Utils.writeFile(remoteFile, data + data);
 
-                Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
-                Path remoteFile = remoteDir.resolve(localFile.getFileName());
-                Utils.writeFile(remoteFile, data + data);
-
-                String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
-                scp.upload(localFile.toString(), remotePath);
-                assertFileLength(remoteFile, data.length(), TimeUnit.SECONDS.toMillis(5L));
-            } finally {
-                client.stop();
-            }
+            String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
+            scp.upload(localFile.toString(), remotePath);
+            assertFileLength(remoteFile, data.length(), TimeUnit.SECONDS.toMillis(5L));
         }
     }
 
@@ -316,20 +314,14 @@ public class ScpTest extends BaseTestSupport {
             Files.delete(zeroRemote);
         }
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-                ScpClient scp = createScpClient(session);
-                String remotePath = Utils.resolveRelativeRemotePath(targetPath.getParent(), zeroRemote);
-                scp.upload(zeroLocal.toString(), remotePath);
-                assertFileLength(zeroRemote, 0L, TimeUnit.SECONDS.toMillis(5L));
-            } finally {
-                client.stop();
-            }
+            ScpClient scp = createScpClient(session);
+            String remotePath = Utils.resolveRelativeRemotePath(targetPath.getParent(), zeroRemote);
+            scp.upload(zeroLocal.toString(), remotePath);
+            assertFileLength(zeroRemote, 0L, TimeUnit.SECONDS.toMillis(5L));
         }
     }
 
@@ -352,20 +344,14 @@ public class ScpTest extends BaseTestSupport {
         }
         assertEquals("Non-zero size for remote file=" + zeroRemote, 0L, Files.size(zeroRemote));
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-                ScpClient scp = createScpClient(session);
-                String remotePath = Utils.resolveRelativeRemotePath(targetPath.getParent(), zeroRemote);
-                scp.download(remotePath, zeroLocal.toString());
-                assertFileLength(zeroLocal, 0L, TimeUnit.SECONDS.toMillis(5L));
-            } finally {
-                client.stop();
-            }
+            ScpClient scp = createScpClient(session);
+            String remotePath = Utils.resolveRelativeRemotePath(targetPath.getParent(), zeroRemote);
+            scp.download(remotePath, zeroLocal.toString());
+            assertFileLength(zeroLocal, 0L, TimeUnit.SECONDS.toMillis(5L));
         }
     }
 
@@ -383,352 +369,310 @@ public class ScpTest extends BaseTestSupport {
         Path remoteDir = scpRoot.resolve("remote");
         Path remoteOutFile = remoteDir.resolve(localOutFile.getFileName());
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+            ScpClient scp = createScpClient(session);
+            Utils.writeFile(localOutFile, data);
 
-                ScpClient scp = createScpClient(session);
-                Utils.writeFile(localOutFile, data);
-
-                assertFalse("Remote folder already exists: " + remoteDir, Files.exists(remoteDir));
-
-                String localOutPath = localOutFile.toString();
-                String remoteOutPath = Utils.resolveRelativeRemotePath(parentPath, remoteOutFile);
-                outputDebugMessage("Expect upload failure %s => %s", localOutPath, remoteOutPath);
-                try {
-                    scp.upload(localOutPath, remoteOutPath);
-                    fail("Expected IOException for 1st time " + remoteOutPath);
-                } catch (IOException e) {
-                    // ok
-                }
+            assertFalse("Remote folder already exists: " + remoteDir, Files.exists(remoteDir));
 
-                assertHierarchyTargetFolderExists(remoteDir);
-                outputDebugMessage("Expect upload success %s => %s", localOutPath, remoteOutPath);
+            String localOutPath = localOutFile.toString();
+            String remoteOutPath = Utils.resolveRelativeRemotePath(parentPath, remoteOutFile);
+            outputDebugMessage("Expect upload failure %s => %s", localOutPath, remoteOutPath);
+            try {
                 scp.upload(localOutPath, remoteOutPath);
-                assertFileLength(remoteOutFile, data.length(), TimeUnit.SECONDS.toMillis(5L));
-
-                Path secondLocal = localDir.resolve(localOutFile.getFileName());
-                String downloadTarget = Utils.resolveRelativeRemotePath(parentPath, secondLocal);
-                outputDebugMessage("Expect download success %s => %s", remoteOutPath, downloadTarget);
-                scp.download(remoteOutPath, downloadTarget);
-                assertFileLength(secondLocal, data.length(), TimeUnit.SECONDS.toMillis(5L));
-
-                Path localPath = localDir.resolve("file-path.txt");
-                downloadTarget = Utils.resolveRelativeRemotePath(parentPath, localPath);
-                outputDebugMessage("Expect download success %s => %s", remoteOutPath, downloadTarget);
-                scp.download(remoteOutPath, downloadTarget);
-                assertFileLength(localPath, data.length(), TimeUnit.SECONDS.toMillis(5L));
-            } finally {
-                client.stop();
+                fail("Expected IOException for 1st time " + remoteOutPath);
+            } catch (IOException e) {
+                // ok
             }
+
+            assertHierarchyTargetFolderExists(remoteDir);
+            outputDebugMessage("Expect upload success %s => %s", localOutPath, remoteOutPath);
+            scp.upload(localOutPath, remoteOutPath);
+            assertFileLength(remoteOutFile, data.length(), TimeUnit.SECONDS.toMillis(5L));
+
+            Path secondLocal = localDir.resolve(localOutFile.getFileName());
+            String downloadTarget = Utils.resolveRelativeRemotePath(parentPath, secondLocal);
+            outputDebugMessage("Expect download success %s => %s", remoteOutPath, downloadTarget);
+            scp.download(remoteOutPath, downloadTarget);
+            assertFileLength(secondLocal, data.length(), TimeUnit.SECONDS.toMillis(5L));
+
+            Path localPath = localDir.resolve("file-path.txt");
+            downloadTarget = Utils.resolveRelativeRemotePath(parentPath, localPath);
+            outputDebugMessage("Expect download success %s => %s", remoteOutPath, downloadTarget);
+            scp.download(remoteOutPath, downloadTarget);
+            assertFileLength(localPath, data.length(), TimeUnit.SECONDS.toMillis(5L));
         }
     }
 
     @Test
     public void testScpNativeOnMultipleFiles() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                ScpClient scp = createScpClient(session);
-                Path targetPath = detectTargetFolder();
-                Path parentPath = targetPath.getParent();
-                Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
-                Utils.deleteRecursive(scpRoot);
-
-                Path localDir = assertHierarchyTargetFolderExists(scpRoot.resolve("local"));
-                Path local1 = localDir.resolve("file-1.txt");
-                byte[] data = Utils.writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
-
-                Path local2 = localDir.resolve("file-2.txt");
-                Files.write(local2, data);
-
-                Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
-                Path remote1 = remoteDir.resolve(local1.getFileName());
-                String remote1Path = Utils.resolveRelativeRemotePath(parentPath, remote1);
-                String[] locals = {local1.toString(), local2.toString()};
-                try {
-                    scp.upload(locals, remote1Path);
-                    fail("Unexpected upload success to missing remote file: " + remote1Path);
-                } catch (IOException e) {
-                    // Ok
-                }
-
-                Files.write(remote1, data);
-                try {
-                    scp.upload(locals, remote1Path);
-                    fail("Unexpected upload success to existing remote file: " + remote1Path);
-                } catch (IOException e) {
-                    // Ok
-                }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            ScpClient scp = createScpClient(session);
+            Path targetPath = detectTargetFolder();
+            Path parentPath = targetPath.getParent();
+            Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
+            Utils.deleteRecursive(scpRoot);
+
+            Path localDir = assertHierarchyTargetFolderExists(scpRoot.resolve("local"));
+            Path local1 = localDir.resolve("file-1.txt");
+            byte[] data = Utils.writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
+
+            Path local2 = localDir.resolve("file-2.txt");
+            Files.write(local2, data);
+
+            Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
+            Path remote1 = remoteDir.resolve(local1.getFileName());
+            String remote1Path = Utils.resolveRelativeRemotePath(parentPath, remote1);
+            String[] locals = {local1.toString(), local2.toString()};
+            try {
+                scp.upload(locals, remote1Path);
+                fail("Unexpected upload success to missing remote file: " + remote1Path);
+            } catch (IOException e) {
+                // Ok
+            }
 
-                Path remoteSubDir = assertHierarchyTargetFolderExists(remoteDir.resolve("dir"));
-                scp.upload(locals, Utils.resolveRelativeRemotePath(parentPath, remoteSubDir));
+            Files.write(remote1, data);
+            try {
+                scp.upload(locals, remote1Path);
+                fail("Unexpected upload success to existing remote file: " + remote1Path);
+            } catch (IOException e) {
+                // Ok
+            }
 
-                Path remoteSub1 = remoteSubDir.resolve(local1.getFileName());
-                assertFileLength(remoteSub1, data.length, TimeUnit.SECONDS.toMillis(5L));
+            Path remoteSubDir = assertHierarchyTargetFolderExists(remoteDir.resolve("dir"));
+            scp.upload(locals, Utils.resolveRelativeRemotePath(parentPath, remoteSubDir));
 
-                Path remoteSub2 = remoteSubDir.resolve(local2.getFileName());
-                assertFileLength(remoteSub2, data.length, TimeUnit.SECONDS.toMillis(5L));
+            Path remoteSub1 = remoteSubDir.resolve(local1.getFileName());
+            assertFileLength(remoteSub1, data.length, TimeUnit.SECONDS.toMillis(5L));
 
-                String[] remotes = {
-                        Utils.resolveRelativeRemotePath(parentPath, remoteSub1),
-                        Utils.resolveRelativeRemotePath(parentPath, remoteSub2),
-                };
+            Path remoteSub2 = remoteSubDir.resolve(local2.getFileName());
+            assertFileLength(remoteSub2, data.length, TimeUnit.SECONDS.toMillis(5L));
 
-                try {
-                    scp.download(remotes, Utils.resolveRelativeRemotePath(parentPath, local1));
-                    fail("Unexpected download success to existing local file: " + local1);
-                } catch (IOException e) {
-                    // Ok
-                }
+            String[] remotes = {
+                    Utils.resolveRelativeRemotePath(parentPath, remoteSub1),
+                    Utils.resolveRelativeRemotePath(parentPath, remoteSub2),
+            };
 
-                Path localSubDir = localDir.resolve("dir");
-                try {
-                    scp.download(remotes, localSubDir);
-                    fail("Unexpected download success to non-existing folder: " + localSubDir);
-                } catch (IOException e) {
-                    // Ok
-                }
+            try {
+                scp.download(remotes, Utils.resolveRelativeRemotePath(parentPath, local1));
+                fail("Unexpected download success to existing local file: " + local1);
+            } catch (IOException e) {
+                // Ok
+            }
 
-                assertHierarchyTargetFolderExists(localSubDir);
+            Path localSubDir = localDir.resolve("dir");
+            try {
                 scp.download(remotes, localSubDir);
-
-                assertFileLength(localSubDir.resolve(remoteSub1.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
-                assertFileLength(localSubDir.resolve(remoteSub2.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
-            } finally {
-                client.stop();
+                fail("Unexpected download success to non-existing folder: " + localSubDir);
+            } catch (IOException e) {
+                // Ok
             }
+
+            assertHierarchyTargetFolderExists(localSubDir);
+            scp.download(remotes, localSubDir);
+
+            assertFileLength(localSubDir.resolve(remoteSub1.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
+            assertFileLength(localSubDir.resolve(remoteSub2.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
         }
     }
 
     @Test
     public void testScpNativeOnRecursiveDirs() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                ScpClient scp = createScpClient(session);
-                Path targetPath = detectTargetFolder();
-                Path parentPath = targetPath.getParent();
-                Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
-                Utils.deleteRecursive(scpRoot);
-
-                Path localDir = scpRoot.resolve("local");
-                Path localSubDir = assertHierarchyTargetFolderExists(localDir.resolve("dir"));
-                Path localSub1 = localSubDir.resolve("file-1.txt");
-                byte[] data = Utils.writeFile(localSub1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
-                Path localSub2 = localSubDir.resolve("file-2.txt");
-                Files.write(localSub2, data);
-
-                Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
-                scp.upload(localSubDir, Utils.resolveRelativeRemotePath(parentPath, remoteDir), ScpClient.Option.Recursive);
-
-                Path remoteSubDir = remoteDir.resolve(localSubDir.getFileName());
-                assertFileLength(remoteSubDir.resolve(localSub1.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
-                assertFileLength(remoteSubDir.resolve(localSub2.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
-
-                Utils.deleteRecursive(localSubDir);
-
-                scp.download(Utils.resolveRelativeRemotePath(parentPath, remoteSubDir), localDir, ScpClient.Option.Recursive);
-                assertFileLength(localSub1, data.length, TimeUnit.SECONDS.toMillis(5L));
-                assertFileLength(localSub2, data.length, TimeUnit.SECONDS.toMillis(5L));
-            } finally {
-                client.stop();
-            }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            ScpClient scp = createScpClient(session);
+            Path targetPath = detectTargetFolder();
+            Path parentPath = targetPath.getParent();
+            Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
+            Utils.deleteRecursive(scpRoot);
+
+            Path localDir = scpRoot.resolve("local");
+            Path localSubDir = assertHierarchyTargetFolderExists(localDir.resolve("dir"));
+            Path localSub1 = localSubDir.resolve("file-1.txt");
+            byte[] data = Utils.writeFile(localSub1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
+            Path localSub2 = localSubDir.resolve("file-2.txt");
+            Files.write(localSub2, data);
+
+            Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
+            scp.upload(localSubDir, Utils.resolveRelativeRemotePath(parentPath, remoteDir), ScpClient.Option.Recursive);
+
+            Path remoteSubDir = remoteDir.resolve(localSubDir.getFileName());
+            assertFileLength(remoteSubDir.resolve(localSub1.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
+            assertFileLength(remoteSubDir.resolve(localSub2.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
+
+            Utils.deleteRecursive(localSubDir);
+
+            scp.download(Utils.resolveRelativeRemotePath(parentPath, remoteSubDir), localDir, ScpClient.Option.Recursive);
+            assertFileLength(localSub1, data.length, TimeUnit.SECONDS.toMillis(5L));
+            assertFileLength(localSub2, data.length, TimeUnit.SECONDS.toMillis(5L));
         }
     }
 
     @Test
     public void testScpNativeOnDirWithPattern() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                ScpClient scp = createScpClient(session);
-                Path targetPath = detectTargetFolder();
-                Path parentPath = targetPath.getParent();
-                Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
-                Utils.deleteRecursive(scpRoot);
-
-                Path localDir = assertHierarchyTargetFolderExists(scpRoot.resolve("local"));
-                Path local1 = localDir.resolve("file-1.txt");
-                byte[] data = Utils.writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
-                Path local2 = localDir.resolve("file-2.txt");
-                Files.write(local2, data);
-
-                Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
-                String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteDir);
-                scp.upload(localDir.toString() + File.separator + "*", remotePath);
-                assertFileLength(remoteDir.resolve(local1.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
-                assertFileLength(remoteDir.resolve(local2.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
-
-                Files.delete(local1);
-                Files.delete(local2);
-                scp.download(remotePath + "/*", localDir);
-                assertFileLength(local1, data.length, TimeUnit.SECONDS.toMillis(5L));
-                assertFileLength(local2, data.length, TimeUnit.SECONDS.toMillis(5L));
-            } finally {
-                client.stop();
-            }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            ScpClient scp = createScpClient(session);
+            Path targetPath = detectTargetFolder();
+            Path parentPath = targetPath.getParent();
+            Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
+            Utils.deleteRecursive(scpRoot);
+
+            Path localDir = assertHierarchyTargetFolderExists(scpRoot.resolve("local"));
+            Path local1 = localDir.resolve("file-1.txt");
+            byte[] data = Utils.writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
+            Path local2 = localDir.resolve("file-2.txt");
+            Files.write(local2, data);
+
+            Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
+            String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteDir);
+            scp.upload(localDir.toString() + File.separator + "*", remotePath);
+            assertFileLength(remoteDir.resolve(local1.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
+            assertFileLength(remoteDir.resolve(local2.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
+
+            Files.delete(local1);
+            Files.delete(local2);
+            scp.download(remotePath + "/*", localDir);
+            assertFileLength(local1, data.length, TimeUnit.SECONDS.toMillis(5L));
+            assertFileLength(local2, data.length, TimeUnit.SECONDS.toMillis(5L));
         }
     }
 
     @Test
     public void testScpNativeOnMixedDirAndFiles() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                ScpClient scp = createScpClient(session);
-                Path targetPath = detectTargetFolder();
-                Path parentPath = targetPath.getParent();
-                Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
-                Utils.deleteRecursive(scpRoot);
-
-                Path localDir = scpRoot.resolve("local");
-                Path localSubDir = assertHierarchyTargetFolderExists(localDir.resolve("dir"));
-                Path local1 = localDir.resolve("file-1.txt");
-                byte[] data = Utils.writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
-                Path localSub2 = localSubDir.resolve("file-2.txt");
-                Files.write(localSub2, data);
-
-                Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
-                String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteDir);
-                scp.upload(localDir.toString() + File.separator + "*", remotePath, ScpClient.Option.Recursive);
-                assertFileLength(remoteDir.resolve(local1.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
-
-                Path remoteSubDir = remoteDir.resolve(localSubDir.getFileName());
-                assertFileLength(remoteSubDir.resolve(localSub2.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
-
-                Files.delete(local1);
-                Utils.deleteRecursive(localSubDir);
-
-                scp.download(remotePath + "/*", localDir);
-                assertFileLength(local1, data.length, TimeUnit.SECONDS.toMillis(5L));
-                assertFalse("Unexpected recursive local file: " + localSub2, Files.exists(localSub2));
-
-                Files.delete(local1);
-                scp.download(remotePath + "/*", localDir, ScpClient.Option.Recursive);
-                assertFileLength(local1, data.length, TimeUnit.SECONDS.toMillis(5L));
-                assertFileLength(localSub2, data.length, TimeUnit.SECONDS.toMillis(5L));
-            } finally {
-                client.stop();
-            }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            ScpClient scp = createScpClient(session);
+            Path targetPath = detectTargetFolder();
+            Path parentPath = targetPath.getParent();
+            Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
+            Utils.deleteRecursive(scpRoot);
+
+            Path localDir = scpRoot.resolve("local");
+            Path localSubDir = assertHierarchyTargetFolderExists(localDir.resolve("dir"));
+            Path local1 = localDir.resolve("file-1.txt");
+            byte[] data = Utils.writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
+            Path localSub2 = localSubDir.resolve("file-2.txt");
+            Files.write(localSub2, data);
+
+            Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
+            String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteDir);
+            scp.upload(localDir.toString() + File.separator + "*", remotePath, ScpClient.Option.Recursive);
+            assertFileLength(remoteDir.resolve(local1.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
+
+            Path remoteSubDir = remoteDir.resolve(localSubDir.getFileName());
+            assertFileLength(remoteSubDir.resolve(localSub2.getFileName()), data.length, TimeUnit.SECONDS.toMillis(5L));
+
+            Files.delete(local1);
+            Utils.deleteRecursive(localSubDir);
+
+            scp.download(remotePath + "/*", localDir);
+            assertFileLength(local1, data.length, TimeUnit.SECONDS.toMillis(5L));
+            assertFalse("Unexpected recursive local file: " + localSub2, Files.exists(localSub2));
+
+            Files.delete(local1);
+            scp.download(remotePath + "/*", localDir, ScpClient.Option.Recursive);
+            assertFileLength(local1, data.length, TimeUnit.SECONDS.toMillis(5L));
+            assertFileLength(localSub2, data.length, TimeUnit.SECONDS.toMillis(5L));
         }
     }
 
     @Test
     public void testScpNativePreserveAttributes() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                ScpClient scp = createScpClient(session);
-                Path targetPath = detectTargetFolder();
-                Path parentPath = targetPath.getParent();
-                Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
-                Utils.deleteRecursive(scpRoot);
-
-                Path localDir = scpRoot.resolve("local");
-                Path localSubDir = assertHierarchyTargetFolderExists(localDir.resolve("dir"));
-                // convert everything to seconds since this is the SCP timestamps granularity
-                final long lastModMillis = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
-                final long lastModSecs = TimeUnit.MILLISECONDS.toSeconds(lastModMillis);
-                Path local1 = localDir.resolve("file-1.txt");
-                byte[] data = Utils.writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
-
-                File lclFile1 = local1.toFile();
-                boolean lcl1ModSet = lclFile1.setLastModified(lastModMillis);
-                lclFile1.setExecutable(true, true);
-                lclFile1.setWritable(false, false);
-
-                Path localSub2 = localSubDir.resolve("file-2.txt");
-                Files.write(localSub2, data);
-                File lclSubFile2 = localSub2.toFile();
-                boolean lclSub2ModSet = lclSubFile2.setLastModified(lastModMillis);
-
-                Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
-                String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteDir);
-                scp.upload(localDir.toString() + File.separator + "*", remotePath, ScpClient.Option.Recursive, ScpClient.Option.PreserveAttributes);
-
-                Path remote1 = remoteDir.resolve(local1.getFileName());
-                assertFileLength(remote1, data.length, TimeUnit.SECONDS.toMillis(5L));
-
-                File remFile1 = remote1.toFile();
-                assertLastModifiedTimeEquals(remFile1, lcl1ModSet, lastModSecs);
-
-                Path remoteSubDir = remoteDir.resolve(localSubDir.getFileName());
-                Path remoteSub2 = remoteSubDir.resolve(localSub2.getFileName());
-                assertFileLength(remoteSub2, data.length, TimeUnit.SECONDS.toMillis(5L));
-
-                File remSubFile2 = remoteSub2.toFile();
-                assertLastModifiedTimeEquals(remSubFile2, lclSub2ModSet, lastModSecs);
-
-                Utils.deleteRecursive(localDir);
-                assertHierarchyTargetFolderExists(localDir);
-
-                scp.download(remotePath + "/*", localDir, ScpClient.Option.Recursive, ScpClient.Option.PreserveAttributes);
-                assertFileLength(local1, data.length, TimeUnit.SECONDS.toMillis(5L));
-                assertLastModifiedTimeEquals(lclFile1, lcl1ModSet, lastModSecs);
-                assertFileLength(localSub2, data.length, TimeUnit.SECONDS.toMillis(5L));
-                assertLastModifiedTimeEquals(lclSubFile2, lclSub2ModSet, lastModSecs);
-            } finally {
-                client.stop();
-            }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            ScpClient scp = createScpClient(session);
+            Path targetPath = detectTargetFolder();
+            Path parentPath = targetPath.getParent();
+            Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
+            Utils.deleteRecursive(scpRoot);
+
+            Path localDir = scpRoot.resolve("local");
+            Path localSubDir = assertHierarchyTargetFolderExists(localDir.resolve("dir"));
+            // convert everything to seconds since this is the SCP timestamps granularity
+            final long lastModMillis = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
+            final long lastModSecs = TimeUnit.MILLISECONDS.toSeconds(lastModMillis);
+            Path local1 = localDir.resolve("file-1.txt");
+            byte[] data = Utils.writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
+
+            File lclFile1 = local1.toFile();
+            boolean lcl1ModSet = lclFile1.setLastModified(lastModMillis);
+            lclFile1.setExecutable(true, true);
+            lclFile1.setWritable(false, false);
+
+            Path localSub2 = localSubDir.resolve("file-2.txt");
+            Files.write(localSub2, data);
+            File lclSubFile2 = localSub2.toFile();
+            boolean lclSub2ModSet = lclSubFile2.setLastModified(lastModMillis);
+
+            Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
+            String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteDir);
+            scp.upload(localDir.toString() + File.separator + "*", remotePath, ScpClient.Option.Recursive, ScpClient.Option.PreserveAttributes);
+
+            Path remote1 = remoteDir.resolve(local1.getFileName());
+            assertFileLength(remote1, data.length, TimeUnit.SECONDS.toMillis(5L));
+
+            File remFile1 = remote1.toFile();
+            assertLastModifiedTimeEquals(remFile1, lcl1ModSet, lastModSecs);
+
+            Path remoteSubDir = remoteDir.resolve(localSubDir.getFileName());
+            Path remoteSub2 = remoteSubDir.resolve(localSub2.getFileName());
+            assertFileLength(remoteSub2, data.length, TimeUnit.SECONDS.toMillis(5L));
+
+            File remSubFile2 = remoteSub2.toFile();
+            assertLastModifiedTimeEquals(remSubFile2, lclSub2ModSet, lastModSecs);
+
+            Utils.deleteRecursive(localDir);
+            assertHierarchyTargetFolderExists(localDir);
+
+            scp.download(remotePath + "/*", localDir, ScpClient.Option.Recursive, ScpClient.Option.PreserveAttributes);
+            assertFileLength(local1, data.length, TimeUnit.SECONDS.toMillis(5L));
+            assertLastModifiedTimeEquals(lclFile1, lcl1ModSet, lastModSecs);
+            assertFileLength(localSub2, data.length, TimeUnit.SECONDS.toMillis(5L));
+            assertLastModifiedTimeEquals(lclSubFile2, lclSub2ModSet, lastModSecs);
         }
     }
 
     @Test
     public void testStreamsUploadAndDownload() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                ScpClient scp = createScpClient(session);
-                Path targetPath = detectTargetFolder();
-                Path parentPath = targetPath.getParent();
-                Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
-                Utils.deleteRecursive(scpRoot);
-
-                Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
-                Path remoteFile = remoteDir.resolve("file.txt");
-                String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
-                byte[] data = (getClass().getName() + "#" + getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
-                outputDebugMessage("Upload data to %s", remotePath);
-                scp.upload(data, remotePath, EnumSet.allOf(PosixFilePermission.class), null);
-                assertFileLength(remoteFile, data.length, TimeUnit.SECONDS.toMillis(5L));
-
-                byte[] uploaded = Files.readAllBytes(remoteFile);
-                assertArrayEquals("Mismatched uploaded data", data, uploaded);
-
-                outputDebugMessage("Download data from %s", remotePath);
-                byte[] downloaded = scp.downloadBytes(remotePath);
-                assertArrayEquals("Mismatched downloaded data", uploaded, downloaded);
-            } finally {
-                client.stop();
-            }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            ScpClient scp = createScpClient(session);
+            Path targetPath = detectTargetFolder();
+            Path parentPath = targetPath.getParent();
+            Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
+            Utils.deleteRecursive(scpRoot);
+
+            Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
+            Path remoteFile = remoteDir.resolve("file.txt");
+            String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
+            byte[] data = (getClass().getName() + "#" + getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
+            outputDebugMessage("Upload data to %s", remotePath);
+            scp.upload(data, remotePath, EnumSet.allOf(PosixFilePermission.class), null);
+            assertFileLength(remoteFile, data.length, TimeUnit.SECONDS.toMillis(5L));
+
+            byte[] uploaded = Files.readAllBytes(remoteFile);
+            assertArrayEquals("Mismatched uploaded data", data, uploaded);
+
+            outputDebugMessage("Download data from %s", remotePath);
+            byte[] downloaded = scp.downloadBytes(remotePath);
+            assertArrayEquals("Mismatched downloaded data", uploaded, downloaded);
         }
     }
 
@@ -766,58 +710,54 @@ public class ScpTest extends BaseTestSupport {
         }
 
         ScpCommandFactory factory = (ScpCommandFactory) sshd.getCommandFactory();
+        ScpFileOpener opener = factory.getScpFileOpener();
         TrackingFileOpener serverOpener = new TrackingFileOpener();
         factory.setScpFileOpener(serverOpener);
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                TrackingFileOpener clientOpener = new TrackingFileOpener();
-                ScpClient scp = session.createScpClient(clientOpener);
+            TrackingFileOpener clientOpener = new TrackingFileOpener();
+            ScpClient scp = session.createScpClient(clientOpener);
 
-                Path targetPath = detectTargetFolder();
-                Path parentPath = targetPath.getParent();
-                Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
-                Utils.deleteRecursive(scpRoot);
+            Path targetPath = detectTargetFolder();
+            Path parentPath = targetPath.getParent();
+            Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
+            Utils.deleteRecursive(scpRoot);
 
-                Path remoteDir = assertHierarchyTargetFolderExists(scpRoot);
-                Path localFile = remoteDir.resolve("data.txt");
-                byte[] data = (getClass().getName() + "#" + getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
-                Files.write(localFile, data);
+            Path remoteDir = assertHierarchyTargetFolderExists(scpRoot);
+            Path localFile = remoteDir.resolve("data.txt");
+            byte[] data = (getClass().getName() + "#" + getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
+            Files.write(localFile, data);
 
-                Path remoteFile = remoteDir.resolve("upload.txt");
-                String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
-                outputDebugMessage("Upload data to %s", remotePath);
-                scp.upload(localFile, remotePath);
-                assertFileLength(remoteFile, data.length, TimeUnit.SECONDS.toMillis(5L));
+            Path remoteFile = remoteDir.resolve("upload.txt");
+            String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
+            outputDebugMessage("Upload data to %s", remotePath);
+            scp.upload(localFile, remotePath);
+            assertFileLength(remoteFile, data.length, TimeUnit.SECONDS.toMillis(5L));
 
-                AtomicInteger serverRead = serverOpener.getReadCount();
-                assertEquals("Mismatched server upload open read count", 0, serverRead.get());
+            AtomicInteger serverRead = serverOpener.getReadCount();
+            assertEquals("Mismatched server upload open read count", 0, serverRead.get());
 
-                AtomicInteger serverWrite = serverOpener.getWriteCount();
-                assertEquals("Mismatched server upload write count", 1, serverWrite.getAndSet(0));
+            AtomicInteger serverWrite = serverOpener.getWriteCount();
+            assertEquals("Mismatched server upload write count", 1, serverWrite.getAndSet(0));
 
-                AtomicInteger clientRead = clientOpener.getReadCount();
-                assertEquals("Mismatched client upload read count", 1, clientRead.getAndSet(0));
+            AtomicInteger clientRead = clientOpener.getReadCount();
+            assertEquals("Mismatched client upload read count", 1, clientRead.getAndSet(0));
 
-                AtomicInteger clientWrite = clientOpener.getWriteCount();
-                assertEquals("Mismatched client upload write count", 0, clientWrite.get());
+            AtomicInteger clientWrite = clientOpener.getWriteCount();
+            assertEquals("Mismatched client upload write count", 0, clientWrite.get());
 
-                Files.delete(localFile);
-                scp.download(remotePath, localFile);
-                assertFileLength(localFile, data.length, TimeUnit.SECONDS.toMillis(5L));
+            Files.delete(localFile);
+            scp.download(remotePath, localFile);
+            assertFileLength(localFile, data.length, TimeUnit.SECONDS.toMillis(5L));
 
-                assertEquals("Mismatched server download open read count", 1, serverRead.getAndSet(0));
-                assertEquals("Mismatched server download write count", 0, serverWrite.get());
-                assertEquals("Mismatched client download read count", 0, clientRead.get());
-                assertEquals("Mismatched client download write count", 1, clientWrite.getAndSet(0));
-            } finally {
-                client.stop();
-            }
+            assertEquals("Mismatched server download open read count", 1, serverRead.getAndSet(0));
+            assertEquals("Mismatched server download write count", 0, serverWrite.get());
+            assertEquals("Mismatched client download read count", 0, clientRead.get());
+            assertEquals("Mismatched client download write count", 1, clientWrite.getAndSet(0));
+        } finally {
+            factory.setScpFileOpener(opener);
         }
     }
 
@@ -859,6 +799,8 @@ public class ScpTest extends BaseTestSupport {
                 }
             }
         }
+
+        ScpCommandFactory factory = (ScpCommandFactory) sshd.getCommandFactory();
         sshd.setCommandFactory(new ScpCommandFactory() {
             @Override
             public Command createCommand(String command) {
@@ -870,52 +812,48 @@ public class ScpTest extends BaseTestSupport {
             }
         });
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                ScpClient scp = session.createScpClient();
-                Path targetPath = detectTargetFolder();
-                Path parentPath = targetPath.getParent();
-                Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
-                Utils.deleteRecursive(scpRoot);
-
-                Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
-                Path remoteFile = remoteDir.resolve("file.txt");
-                String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
-                byte[] data = (getClass().getName() + "#" + getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
-                outputDebugMessage("Upload data to %s", remotePath);
-                try {
-                    scp.upload(data, remotePath, EnumSet.allOf(PosixFilePermission.class), null);
-                    outputDebugMessage("Upload success to %s", remotePath);
-                } catch (ScpException e) {
-                    Integer exitCode = e.getExitStatus();
-                    assertNotNull("No upload exit status", exitCode);
-                    assertEquals("Mismatched upload exit status", testExitValue, exitCode.intValue());
-                }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            ScpClient scp = session.createScpClient();
+            Path targetPath = detectTargetFolder();
+            Path parentPath = targetPath.getParent();
+            Path scpRoot = Utils.resolve(targetPath, ScpHelper.SCP_COMMAND_PREFIX, getClass().getSimpleName(), getCurrentTestName());
+            Utils.deleteRecursive(scpRoot);
+
+            Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
+            Path remoteFile = remoteDir.resolve("file.txt");
+            String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
+            byte[] data = (getClass().getName() + "#" + getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
+            outputDebugMessage("Upload data to %s", remotePath);
+            try {
+                scp.upload(data, remotePath, EnumSet.allOf(PosixFilePermission.class), null);
+                outputDebugMessage("Upload success to %s", remotePath);
+            } catch (ScpException e) {
+                Integer exitCode = e.getExitStatus();
+                assertNotNull("No upload exit status", exitCode);
+                assertEquals("Mismatched upload exit status", testExitValue, exitCode.intValue());
+            }
 
-                if (Files.deleteIfExists(remoteFile)) {
-                    outputDebugMessage("Deleted remote file %s", remoteFile);
-                }
+            if (Files.deleteIfExists(remoteFile)) {
+                outputDebugMessage("Deleted remote file %s", remoteFile);
+            }
 
-                try (OutputStream out = Files.newOutputStream(remoteFile)) {
-                    out.write(data);
-                }
+            try (OutputStream out = Files.newOutputStream(remoteFile)) {
+                out.write(data);
+            }
 
-                try {
-                    byte[] downloaded = scp.downloadBytes(remotePath);
-                    outputDebugMessage("Download success to %s: %s", remotePath, new String(downloaded, StandardCharsets.UTF_8));
-                } catch (ScpException e) {
-                    Integer exitCode = e.getExitStatus();
-                    assertNotNull("No download exit status", exitCode);
-                    assertEquals("Mismatched download exit status", testExitValue, exitCode.intValue());
-                }
-            } finally {
-                client.stop();
+            try {
+                byte[] downloaded = scp.downloadBytes(remotePath);
+                outputDebugMessage("Download success to %s: %s", remotePath, new String(downloaded, StandardCharsets.UTF_8));
+            } catch (ScpException e) {
+                Integer exitCode = e.getExitStatus();
+                assertNotNull("No download exit status", exitCode);
+                assertEquals("Mismatched download exit status", testExitValue, exitCode.intValue());
             }
+        } finally {
+            sshd.setCommandFactory(factory);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/session/ClientSessionTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/session/ClientSessionTest.java b/sshd-core/src/test/java/org/apache/sshd/client/session/ClientSessionTest.java
index 52b8faa..103a42b 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/session/ClientSessionTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/session/ClientSessionTest.java
@@ -31,8 +31,9 @@ import org.apache.sshd.server.CommandFactory;
 import org.apache.sshd.server.SshServer;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.CommandExecutionHelper;
-import org.junit.After;
-import org.junit.Before;
+import org.apache.sshd.util.test.Utils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
@@ -42,31 +43,40 @@ import org.junit.runners.MethodSorters;
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class ClientSessionTest extends BaseTestSupport {
-    private SshServer sshd;
-    private SshClient client;
-    private int port;
+    private static SshServer sshd;
+    private static SshClient client;
+    private static int port;
 
     public ClientSessionTest() {
         super();
     }
 
-    @Before
-    public void setUp() throws Exception {
-        sshd = setupTestServer();
+    @BeforeClass
+    public static void setupClientAndServer() throws Exception {
+        sshd = Utils.setupTestServer(ClientSessionTest.class);
         sshd.start();
         port = sshd.getPort();
 
-        client = setupTestClient();
+        client = Utils.setupTestClient(ClientSessionTest.class);
         client.start();
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
         if (sshd != null) {
-            sshd.stop(true);
+            try {
+                sshd.stop(true);
+            } finally {
+                sshd = null;
+            }
         }
+
         if (client != null) {
-            client.stop();
+            try {
+                client.stop();
+            } finally {
+                client = null;
+            }
         }
     }
 
@@ -101,8 +111,6 @@ public class ClientSessionTest extends BaseTestSupport {
             // NOTE !!! The LF is only because we are using a buffered reader on the server end to read the command
             String actualResponse = session.executeRemoteCommand(expectedCommand + "\n");
             assertEquals("Mismatched command response", expectedResponse, actualResponse);
-        } finally {
-            client.stop();
         }
     }
 
@@ -149,8 +157,6 @@ public class ClientSessionTest extends BaseTestSupport {
             }
 
             actualErrorMessage = cause.getMessage();
-        } finally {
-            client.stop();
         }
 
         assertEquals("Mismatched captured error message", expectedErrorMessage, actualErrorMessage);
@@ -204,8 +210,6 @@ public class ClientSessionTest extends BaseTestSupport {
             }
 
             actualErrorMessage = cause.getMessage();
-        } finally {
-            client.stop();
         }
 
         assertEquals("Mismatched captured error code", Integer.toString(exepectedErrorCode), actualErrorMessage);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/simple/SimpleSftpClientTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/simple/SimpleSftpClientTest.java b/sshd-core/src/test/java/org/apache/sshd/client/simple/SimpleSftpClientTest.java
index b691a02..aed7641 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/simple/SimpleSftpClientTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/simple/SimpleSftpClientTest.java
@@ -25,8 +25,6 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.EnumSet;
-import java.util.Iterator;
-import java.util.List;
 
 import org.apache.sshd.client.subsystem.sftp.SftpClient;
 import org.apache.sshd.common.NamedFactory;
@@ -108,12 +106,8 @@ public class SimpleSftpClientTest extends BaseSimpleClientTestSupport {
             assertArrayEquals("Mismatched remote written data", written, local);
 
             try (SftpClient.CloseableHandle h = sftp.openDir(remoteFileDir)) {
-                List<SftpClient.DirEntry> dirEntries = sftp.readDir(h);
-                assertNotNull("No dir entries", dirEntries);
-
                 boolean matchFound = false;
-                for (Iterator<SftpClient.DirEntry> it = dirEntries.iterator(); it.hasNext();) {
-                    SftpClient.DirEntry entry = it.next();
+                for (SftpClient.DirEntry entry : sftp.listDir(h)) {
                     String name = entry.getFilename();
                     if (clientFileName.equals(name)) {
                         matchFound = true;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClientTestSupport.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClientTestSupport.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClientTestSupport.java
index 1222232..f2ef1bd 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClientTestSupport.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClientTestSupport.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.nio.file.Path;
 import java.util.Collections;
 
+import org.apache.sshd.client.SshClient;
 import org.apache.sshd.client.subsystem.sftp.extensions.SftpClientExtension;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.file.FileSystemFactory;
@@ -32,13 +33,19 @@ import org.apache.sshd.server.SshServer;
 import org.apache.sshd.server.scp.ScpCommandFactory;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
 import org.apache.sshd.util.test.BaseTestSupport;
+import org.apache.sshd.util.test.JSchLogger;
+import org.apache.sshd.util.test.Utils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
 
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 public abstract class AbstractSftpClientTestSupport extends BaseTestSupport {
-    protected SshServer sshd;
-    protected int port;
+    protected static SshServer sshd;
+    protected static int port;
+    protected static SshClient client;
+
     protected final FileSystemFactory fileSystemFactory;
 
     protected AbstractSftpClientTestSupport() throws IOException {
@@ -47,16 +54,21 @@ public abstract class AbstractSftpClientTestSupport extends BaseTestSupport {
         fileSystemFactory = new VirtualFileSystemFactory(parentPath);
     }
 
-    protected void setupServer() throws Exception {
-        sshd = setupTestServer();
+    @BeforeClass
+    public static void setupClientAndServer() throws Exception {
+        JSchLogger.init();
+        sshd = Utils.setupTestServer(AbstractSftpClientTestSupport.class);
         sshd.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystemFactory()));
         sshd.setCommandFactory(new ScpCommandFactory());
-        sshd.setFileSystemFactory(fileSystemFactory);
         sshd.start();
         port = sshd.getPort();
+
+        client = Utils.setupTestClient(AbstractSftpClientTestSupport.class);
+        client.start();
     }
 
-    protected void tearDownServer() throws Exception {
+    @AfterClass
+    public static void tearDownClientAndServer() throws Exception {
         if (sshd != null) {
             try {
                 sshd.stop(true);
@@ -64,6 +76,18 @@ public abstract class AbstractSftpClientTestSupport extends BaseTestSupport {
                 sshd = null;
             }
         }
+
+        if (client != null) {
+            try {
+                client.stop();
+            } finally {
+                client = null;
+            }
+        }
+    }
+
+    protected void setupServer() throws Exception {
+        sshd.setFileSystemFactory(fileSystemFactory);
     }
 
     protected static final <E extends SftpClientExtension> E assertExtensionCreated(SftpClient sftp, Class<E> type) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
index 3a9ae43..e3ee7ec 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
@@ -71,17 +71,18 @@ import org.apache.sshd.server.subsystem.sftp.SftpSubsystem;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.Utils;
-import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
 
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class SftpFileSystemTest extends BaseTestSupport {
+    private static SshServer sshd;
+    private static int port;
 
-    private SshServer sshd;
-    private int port;
     private final FileSystemFactory fileSystemFactory;
 
     public SftpFileSystemTest() throws IOException {
@@ -90,23 +91,31 @@ public class SftpFileSystemTest extends BaseTestSupport {
         fileSystemFactory = new VirtualFileSystemFactory(parentPath);
     }
 
-    @Before
-    public void setUp() throws Exception {
-        sshd = setupTestServer();
+    @BeforeClass
+    public static void setupServerInstance() throws Exception {
+        sshd = Utils.setupTestServer(SftpFileSystemTest.class);
         sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystemFactory()));
         sshd.setCommandFactory(new ScpCommandFactory());
-        sshd.setFileSystemFactory(fileSystemFactory);
         sshd.start();
         port = sshd.getPort();
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @AfterClass
+    public static void tearDownServerInstance() throws Exception {
         if (sshd != null) {
-            sshd.stop(true);
+            try {
+                sshd.stop(true);
+            } finally {
+                sshd = null;
+            }
         }
     }
 
+    @Before
+    public void setUp() throws Exception {
+        sshd.setFileSystemFactory(fileSystemFactory);
+    }
+
     @Test
     public void testFileSystem() throws Exception {
         try (FileSystem fs = FileSystems.newFileSystem(createDefaultFileSystemURI(),
@@ -125,7 +134,7 @@ public class SftpFileSystemTest extends BaseTestSupport {
 
     @Test   // see SSHD-578
     public void testFileSystemURIParameters() throws Exception {
-        Map<String, Object> params = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER);
+        Map<String, Object> params = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
         params.put("test-class-name", getClass().getSimpleName());
         params.put("test-pkg-name", getClass().getPackage().getName());
         params.put("test-name", getCurrentTestName());
@@ -309,6 +318,7 @@ public class SftpFileSystemTest extends BaseTestSupport {
                 return selected.get();
             }
         };
+
         try (SshClient client = setupTestClient()) {
             client.start();
 
@@ -329,7 +339,6 @@ public class SftpFileSystemTest extends BaseTestSupport {
                 client.stop();
             }
         }
-
     }
 
     private void testFileSystem(FileSystem fs, int version) throws Exception {


[2/4] mina-sshd git commit: [SSHD-691] Attempt to create server instance only once per test as much as possible

Posted by lg...@apache.org.
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
index 3ddfe18..983addf 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
@@ -34,10 +34,10 @@ import java.nio.file.Files;
 import java.nio.file.LinkOption;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.EnumSet;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -89,15 +89,14 @@ import org.apache.sshd.server.subsystem.sftp.AbstractSftpEventListenerAdapter;
 import org.apache.sshd.server.subsystem.sftp.DirectoryHandle;
 import org.apache.sshd.server.subsystem.sftp.FileHandle;
 import org.apache.sshd.server.subsystem.sftp.Handle;
+import org.apache.sshd.server.subsystem.sftp.SftpEventListener;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystem;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
-import org.apache.sshd.util.test.JSchLogger;
 import org.apache.sshd.util.test.SimpleUserInfo;
 import org.apache.sshd.util.test.Utils;
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
@@ -115,11 +114,6 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         super();
     }
 
-    @BeforeClass
-    public static void jschInit() {
-        JSchLogger.init();
-    }
-
     @Before
     public void setUp() throws Exception {
         setupServer();
@@ -134,8 +128,6 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         if (session != null) {
             session.disconnect();
         }
-
-        tearDownServer();
     }
 
     @Test   // see SSHD-547
@@ -152,32 +144,26 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         rnd.fill(expectedRandom);
 
         byte[] expectedText = (getClass().getName() + "#" + getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    String file = Utils.resolveRelativeRemotePath(parentPath, testFile);
-
-                    try (CloseableHandle handle = sftp.open(file, OpenMode.Create, OpenMode.Write, OpenMode.Read, OpenMode.Append)) {
-                        sftp.write(handle, 7365L, expectedRandom);
-                        byte[] actualRandom = new byte[expectedRandom.length];
-                        int readLen = sftp.read(handle, 0L, actualRandom);
-                        assertEquals("Incomplete random data read", expectedRandom.length, readLen);
-                        assertArrayEquals("Mismatched read random data", expectedRandom, actualRandom);
-
-                        sftp.write(handle, 3777347L, expectedText);
-                        byte[] actualText = new byte[expectedText.length];
-                        readLen = sftp.read(handle, actualRandom.length, actualText);
-                        assertEquals("Incomplete text data read", actualText.length, readLen);
-                        assertArrayEquals("Mismatched read text data", expectedText, actualText);
-                    }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient()) {
+                String file = Utils.resolveRelativeRemotePath(parentPath, testFile);
+
+                try (CloseableHandle handle = sftp.open(file, OpenMode.Create, OpenMode.Write, OpenMode.Read, OpenMode.Append)) {
+                    sftp.write(handle, 7365L, expectedRandom);
+                    byte[] actualRandom = new byte[expectedRandom.length];
+                    int readLen = sftp.read(handle, 0L, actualRandom);
+                    assertEquals("Incomplete random data read", expectedRandom.length, readLen);
+                    assertArrayEquals("Mismatched read random data", expectedRandom, actualRandom);
+
+                    sftp.write(handle, 3777347L, expectedText);
+                    byte[] actualText = new byte[expectedText.length];
+                    readLen = sftp.read(handle, actualRandom.length, actualText);
+                    assertEquals("Incomplete text data read", actualText.length, readLen);
+                    assertArrayEquals("Mismatched read text data", expectedText, actualText);
                 }
-            } finally {
-                client.stop();
             }
         }
 
@@ -204,36 +190,32 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         rnd.fill(expected);
         Files.write(testFile, expected);
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    String file = Utils.resolveRelativeRemotePath(parentPath, testFile);
-                    byte[] actual = new byte[expected.length];
-                    int maxAllowed = actual.length / 4;
-                    // allow less than actual
-                    PropertyResolverUtils.updateProperty(sshd, SftpSubsystem.MAX_PACKET_LENGTH_PROP, maxAllowed);
-                    try (CloseableHandle handle = sftp.open(file, OpenMode.Read)) {
-                        int readLen = sftp.read(handle, 0L, actual);
-                        assertEquals("Mismatched read len", maxAllowed, readLen);
-
-                        for (int index = 0; index < readLen; index++) {
-                            byte expByte = expected[index];
-                            byte actByte = actual[index];
-                            if (expByte != actByte) {
-                                fail("Mismatched values at index=" + index
-                                    + ": expected=0x" + Integer.toHexString(expByte & 0xFF)
-                                    + ", actual=0x" + Integer.toHexString(actByte & 0xFF));
-                            }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient()) {
+                String file = Utils.resolveRelativeRemotePath(parentPath, testFile);
+                byte[] actual = new byte[expected.length];
+                int maxAllowed = actual.length / 4;
+                // allow less than actual
+                PropertyResolverUtils.updateProperty(sshd, SftpSubsystem.MAX_PACKET_LENGTH_PROP, maxAllowed);
+                try (CloseableHandle handle = sftp.open(file, OpenMode.Read)) {
+                    int readLen = sftp.read(handle, 0L, actual);
+                    assertEquals("Mismatched read len", maxAllowed, readLen);
+
+                    for (int index = 0; index < readLen; index++) {
+                        byte expByte = expected[index];
+                        byte actByte = actual[index];
+                        if (expByte != actByte) {
+                            fail("Mismatched values at index=" + index
+                                + ": expected=0x" + Integer.toHexString(expByte & 0xFF)
+                                + ", actual=0x" + Integer.toHexString(actByte & 0xFF));
                         }
                     }
+                } finally {
+                    PropertyResolverUtils.updateProperty(sshd, SftpSubsystem.MAX_PACKET_LENGTH_PROP, SftpSubsystem.DEFAULT_MAX_PACKET_LENGTH);
                 }
-            } finally {
-                client.stop();
             }
         }
     }
@@ -249,20 +231,14 @@ public class SftpTest extends AbstractSftpClientTestSupport {
                 }
             });
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    String rootDir = sftp.canonicalPath("/");
-                    String upDir = sftp.canonicalPath(rootDir + "/..");
-                    assertEquals("Mismatched root dir parent", rootDir, upDir);
-                }
-            } finally {
-                client.stop();
+            try (SftpClient sftp = session.createSftpClient()) {
+                String rootDir = sftp.canonicalPath("/");
+                String upDir = sftp.canonicalPath(rootDir + "/..");
+                assertEquals("Mismatched root dir parent", rootDir, upDir);
             }
         }
     }
@@ -283,70 +259,58 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         assertHierarchyTargetFolderExists(lclSftp);
         sshd.setFileSystemFactory(new VirtualFileSystemFactory(lclSftp));
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-                String escapePath;
-                if (useAbsolutePath) {
-                    escapePath = targetPath.toString();
-                    if (OsUtils.isWin32()) {
-                        escapePath = "/" + escapePath.replace(File.separatorChar, '/');
-                    }
-                } else {
-                    Path parent = lclSftp.getParent();
-                    Path forbidden = Files.createDirectories(parent.resolve("forbidden"));
-                    escapePath = "../" + forbidden.getFileName();
+            String escapePath;
+            if (useAbsolutePath) {
+                escapePath = targetPath.toString();
+                if (OsUtils.isWin32()) {
+                    escapePath = "/" + escapePath.replace(File.separatorChar, '/');
                 }
+            } else {
+                Path parent = lclSftp.getParent();
+                Path forbidden = Files.createDirectories(parent.resolve("forbidden"));
+                escapePath = "../" + forbidden.getFileName();
+            }
 
-                try (SftpClient sftp = session.createSftpClient()) {
-                    SftpClient.Attributes attrs = sftp.stat(escapePath);
-                    fail("Unexpected escape success for path=" + escapePath + ": " + attrs);
-                } catch (SftpException e) {
-                    int expected = OsUtils.isWin32() || (!useAbsolutePath)
-                            ? SftpConstants.SSH_FX_INVALID_FILENAME
-                            : SftpConstants.SSH_FX_NO_SUCH_FILE;
-                    assertEquals("Mismatched status for " + escapePath,
-                                 SftpConstants.getStatusName(expected),
-                                 SftpConstants.getStatusName(e.getStatus()));
-                }
-            } finally {
-                client.stop();
+            try (SftpClient sftp = session.createSftpClient()) {
+                SftpClient.Attributes attrs = sftp.stat(escapePath);
+                fail("Unexpected escape success for path=" + escapePath + ": " + attrs);
+            } catch (SftpException e) {
+                int expected = OsUtils.isWin32() || (!useAbsolutePath)
+                        ? SftpConstants.SSH_FX_INVALID_FILENAME
+                        : SftpConstants.SSH_FX_NO_SUCH_FILE;
+                assertEquals("Mismatched status for " + escapePath,
+                             SftpConstants.getStatusName(expected),
+                             SftpConstants.getStatusName(e.getStatus()));
             }
         }
     }
 
     @Test
     public void testNormalizeRemoteRootValues() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    StringBuilder sb = new StringBuilder(Long.SIZE + 1);
-                    String expected = sftp.canonicalPath("/");
-                    for (int i = 0; i < Long.SIZE; i++) {
-                        if (sb.length() > 0) {
-                            sb.setLength(0);
-                        }
-
-                        for (int j = 1; j <= i; j++) {
-                            sb.append('/');
-                        }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient()) {
+                StringBuilder sb = new StringBuilder(Long.SIZE + 1);
+                String expected = sftp.canonicalPath("/");
+                for (int i = 0; i < Long.SIZE; i++) {
+                    if (sb.length() > 0) {
+                        sb.setLength(0);
+                    }
 
-                        String remotePath = sb.toString();
-                        String actual = sftp.canonicalPath(remotePath);
-                        assertEquals("Mismatched roots for " + remotePath.length() + " slashes", expected, actual);
+                    for (int j = 1; j <= i; j++) {
+                        sb.append('/');
                     }
+
+                    String remotePath = sb.toString();
+                    String actual = sftp.canonicalPath(remotePath);
+                    assertEquals("Mismatched roots for " + remotePath.length() + " slashes", expected, actual);
                 }
-            } finally {
-                client.stop();
             }
         }
     }
@@ -360,42 +324,36 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         String file = Utils.resolveRelativeRemotePath(parentPath, testFile);
         String[] comps = GenericUtils.split(file, '/');
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            Factory<? extends Random> factory = client.getRandomFactory();
-            Random rnd = factory.create();
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    StringBuilder sb = new StringBuilder(file.length() + comps.length);
-                    String expected = sftp.canonicalPath(file);
-                    for (int i = 0; i < file.length(); i++) {
-                        if (sb.length() > 0) {
-                            sb.setLength(0);
-                        }
+        Factory<? extends Random> factory = client.getRandomFactory();
+        Random rnd = factory.create();
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient()) {
+                StringBuilder sb = new StringBuilder(file.length() + comps.length);
+                String expected = sftp.canonicalPath(file);
+                for (int i = 0; i < file.length(); i++) {
+                    if (sb.length() > 0) {
+                        sb.setLength(0);
+                    }
 
-                        sb.append(comps[0]);
-                        for (int j = 1; j < comps.length; j++) {
-                            String name = comps[j];
-                            slashify(sb, rnd);
-                            sb.append(name);
-                        }
+                    sb.append(comps[0]);
+                    for (int j = 1; j < comps.length; j++) {
+                        String name = comps[j];
                         slashify(sb, rnd);
+                        sb.append(name);
+                    }
+                    slashify(sb, rnd);
 
-                        if (rnd.random(Byte.SIZE) < (Byte.SIZE / 2)) {
-                            sb.append('.');
-                        }
-
-                        String remotePath = sb.toString();
-                        String actual = sftp.canonicalPath(remotePath);
-                        assertEquals("Mismatched canonical value for " + remotePath, expected, actual);
+                    if (rnd.random(Byte.SIZE) < (Byte.SIZE / 2)) {
+                        sb.append('.');
                     }
+
+                    String remotePath = sb.toString();
+                    String actual = sftp.canonicalPath(remotePath);
+                    assertEquals("Mismatched canonical value for " + remotePath, expected, actual);
                 }
-            } finally {
-                client.stop();
             }
         }
     }
@@ -421,94 +379,88 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         File javaFile = testFile.toFile();
         assertHierarchyTargetFolderExists(javaFile.getParentFile());
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-                javaFile.createNewFile();
-                javaFile.setWritable(false, false);
-                javaFile.setReadable(false, false);
+            javaFile.createNewFile();
+            javaFile.setWritable(false, false);
+            javaFile.setReadable(false, false);
 
-                try (SftpClient sftp = session.createSftpClient()) {
-                    boolean isWindows = OsUtils.isWin32();
-
-                    try (SftpClient.CloseableHandle h = sftp.open(file /* no mode == read */)) {
-                        // NOTE: on Windows files are always readable
-                        // see https://svn.apache.org/repos/asf/harmony/enhanced/java/branches/java6/classlib/modules/
-                        //      luni/src/test/api/windows/org/apache/harmony/luni/tests/java/io/WinFileTest.java
-                        assertTrue("Empty read should have failed on " + file, isWindows);
-                    } catch (IOException e) {
-                        if (isWindows) {
-                            throw e;
-                        }
-                    }
+            try (SftpClient sftp = session.createSftpClient()) {
+                boolean isWindows = OsUtils.isWin32();
 
-                    try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write))) {
-                        fail("Empty write should have failed on " + file);
-                    } catch (IOException e) {
-                        // ok
+                try (SftpClient.CloseableHandle h = sftp.open(file /* no mode == read */)) {
+                    // NOTE: on Windows files are always readable
+                    // see https://svn.apache.org/repos/asf/harmony/enhanced/java/branches/java6/classlib/modules/
+                    //      luni/src/test/api/windows/org/apache/harmony/luni/tests/java/io/WinFileTest.java
+                    assertTrue("Empty read should have failed on " + file, isWindows);
+                } catch (IOException e) {
+                    if (isWindows) {
+                        throw e;
                     }
+                }
 
-                    try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Truncate))) {
-                        // NOTE: on Windows files are always readable
-                        assertTrue("Empty truncate should have failed on " + file, isWindows);
-                    } catch (IOException e) {
-                        // ok
-                    }
+                try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write))) {
+                    fail("Empty write should have failed on " + file);
+                } catch (IOException e) {
+                    // ok
+                }
 
+                try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Truncate))) {
                     // NOTE: on Windows files are always readable
-                    int perms = sftp.stat(file).getPermissions();
-                    int readMask = isWindows ? 0 : SftpConstants.S_IRUSR;
-                    int permsMask = SftpConstants.S_IWUSR | readMask;
-                    assertEquals("Mismatched permissions for " + file + ": 0x" + Integer.toHexString(perms), 0, perms & permsMask);
+                    assertTrue("Empty truncate should have failed on " + file, isWindows);
+                } catch (IOException e) {
+                    // ok
+                }
 
-                    javaFile.setWritable(true, false);
+                // NOTE: on Windows files are always readable
+                int perms = sftp.stat(file).getPermissions();
+                int readMask = isWindows ? 0 : SftpConstants.S_IRUSR;
+                int permsMask = SftpConstants.S_IWUSR | readMask;
+                assertEquals("Mismatched permissions for " + file + ": 0x" + Integer.toHexString(perms), 0, perms & permsMask);
 
-                    try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Truncate, SftpClient.OpenMode.Write))) {
-                        // OK should succeed
-                        assertTrue("Handle not marked as open for file=" + file, h.isOpen());
-                    }
+                javaFile.setWritable(true, false);
 
-                    byte[] d = "0123456789\n".getBytes(StandardCharsets.UTF_8);
-                    try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write))) {
-                        sftp.write(h, 0, d, 0, d.length);
-                        sftp.write(h, d.length, d, 0, d.length);
-                    }
+                try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Truncate, SftpClient.OpenMode.Write))) {
+                    // OK should succeed
+                    assertTrue("Handle not marked as open for file=" + file, h.isOpen());
+                }
 
-                    try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write))) {
-                        sftp.write(h, d.length * 2, d, 0, d.length);
-                    }
+                byte[] d = "0123456789\n".getBytes(StandardCharsets.UTF_8);
+                try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write))) {
+                    sftp.write(h, 0, d, 0, d.length);
+                    sftp.write(h, d.length, d, 0, d.length);
+                }
 
-                    try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write))) {
-                        byte[] overwrite = "-".getBytes(StandardCharsets.UTF_8);
-                        sftp.write(h, 3L, overwrite, 0, 1);
-                        d[3] = overwrite[0];
-                    }
+                try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write))) {
+                    sftp.write(h, d.length * 2, d, 0, d.length);
+                }
 
-                    try (SftpClient.CloseableHandle h = sftp.open(file /* no mode == read */)) {
-                        // NOTE: on Windows files are always readable
-                        assertTrue("Data read should have failed on " + file, isWindows);
-                    } catch (IOException e) {
-                        if (isWindows) {
-                            throw e;
-                        }
+                try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write))) {
+                    byte[] overwrite = "-".getBytes(StandardCharsets.UTF_8);
+                    sftp.write(h, 3L, overwrite, 0, 1);
+                    d[3] = overwrite[0];
+                }
+
+                try (SftpClient.CloseableHandle h = sftp.open(file /* no mode == read */)) {
+                    // NOTE: on Windows files are always readable
+                    assertTrue("Data read should have failed on " + file, isWindows);
+                } catch (IOException e) {
+                    if (isWindows) {
+                        throw e;
                     }
+                }
 
-                    javaFile.setReadable(true, false);
+                javaFile.setReadable(true, false);
 
-                    byte[] buf = new byte[3];
-                    try (SftpClient.CloseableHandle h = sftp.open(file /* no mode == read */)) {
-                        int l = sftp.read(h, 2L, buf, 0, buf.length);
-                        String expected = new String(d, 2, l, StandardCharsets.UTF_8);
-                        String actual = new String(buf, 0, l, StandardCharsets.UTF_8);
-                        assertEquals("Mismatched read data", expected, actual);
-                    }
+                byte[] buf = new byte[3];
+                try (SftpClient.CloseableHandle h = sftp.open(file /* no mode == read */)) {
+                    int l = sftp.read(h, 2L, buf, 0, buf.length);
+                    String expected = new String(d, 2, l, StandardCharsets.UTF_8);
+                    String actual = new String(buf, 0, l, StandardCharsets.UTF_8);
+                    assertEquals("Mismatched read data", expected, actual);
                 }
-            } finally {
-                client.stop();
             }
         }
     }
@@ -535,8 +487,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         final AtomicInteger removedCount = new AtomicInteger(0);
         final AtomicInteger modifyingCount = new AtomicInteger(0);
         final AtomicInteger modifiedCount = new AtomicInteger(0);
-
-        factory.addSftpEventListener(new AbstractSftpEventListenerAdapter() {
+        SftpEventListener listener = new AbstractSftpEventListenerAdapter() {
             @Override
             public void initialized(ServerSession session, int version) {
                 log.info("initialized(" + session + ") version: " + version);
@@ -686,33 +637,30 @@ public class SftpTest extends AbstractSftpClientTestSupport {
                 log.info("close(" + session + ")[" + remoteHandle + "] " + (Files.isDirectory(path) ? "directory" : "file") + " " + path);
                 closeCount.incrementAndGet();
             }
-        });
-
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+        };
+        factory.addSftpEventListener(listener);
 
-                try (SftpClient sftp = session.createSftpClient()) {
-                    assertEquals("Mismatched negotiated version", sftp.getVersion(), versionHolder.get());
-                    testClient(client, sftp);
-                }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-                assertEquals("Mismatched open/close count", openCount.get(), closeCount.get());
-                assertTrue("No entries read", entriesCount.get() > 0);
-                assertTrue("No data read", readSize.get() > 0L);
-                assertTrue("No data written", writeSize.get() > 0L);
-                assertEquals("Mismatched removal counts", removingCount.get(), removedCount.get());
-                assertTrue("No removals signalled", removedCount.get() > 0);
-                assertEquals("Mismatched creation counts", creatingCount.get(), createdCount.get());
-                assertTrue("No creations signalled", creatingCount.get() > 0);
-                assertEquals("Mismatched modification counts", modifyingCount.get(), modifiedCount.get());
-                assertTrue("No modifications signalled", modifiedCount.get() > 0);
-            } finally {
-                client.stop();
+            try (SftpClient sftp = session.createSftpClient()) {
+                assertEquals("Mismatched negotiated version", sftp.getVersion(), versionHolder.get());
+                testClient(client, sftp);
             }
+
+            assertEquals("Mismatched open/close count", openCount.get(), closeCount.get());
+            assertTrue("No entries read", entriesCount.get() > 0);
+            assertTrue("No data read", readSize.get() > 0L);
+            assertTrue("No data written", writeSize.get() > 0L);
+            assertEquals("Mismatched removal counts", removingCount.get(), removedCount.get());
+            assertTrue("No removals signalled", removedCount.get() > 0);
+            assertEquals("Mismatched creation counts", creatingCount.get(), createdCount.get());
+            assertTrue("No creations signalled", creatingCount.get() > 0);
+            assertEquals("Mismatched modification counts", modifyingCount.get(), modifiedCount.get());
+            assertTrue("No modifications signalled", modifiedCount.get() > 0);
+        } finally {
+            factory.removeSftpEventListener(listener);
         }
     }
 
@@ -725,45 +673,39 @@ public class SftpTest extends AbstractSftpClientTestSupport {
      */
     @Test
     public void testWriteChunking() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                Path targetPath = detectTargetFolder();
-                Path lclSftp = Utils.resolve(targetPath, SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), getCurrentTestName());
-                Utils.deleteRecursive(lclSftp);
-
-                Path parentPath = targetPath.getParent();
-                Path clientFolder = assertHierarchyTargetFolderExists(lclSftp).resolve("client");
-                String dir = Utils.resolveRelativeRemotePath(parentPath, clientFolder);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    sftp.mkdir(dir);
-
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 0, "emptyFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 1000, "smallFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, ByteArrayBuffer.MAX_LEN - 1, "bufferMaxLenMinusOneFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, ByteArrayBuffer.MAX_LEN, "bufferMaxLenFile.txt");
-                    // were chunking not implemented, these would fail. these sizes should invoke our internal chunking mechanism
-                    uploadAndVerifyFile(sftp, clientFolder, dir, ByteArrayBuffer.MAX_LEN + 1, "bufferMaxLenPlusOneFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, (int) (1.5 * ByteArrayBuffer.MAX_LEN), "1point5BufferMaxLenFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, (2 * ByteArrayBuffer.MAX_LEN) - 1, "2TimesBufferMaxLenMinusOneFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 2 * ByteArrayBuffer.MAX_LEN, "2TimesBufferMaxLenFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, (2 * ByteArrayBuffer.MAX_LEN) + 1, "2TimesBufferMaxLenPlusOneFile.txt");
-                    uploadAndVerifyFile(sftp, clientFolder, dir, 200000, "largerFile.txt");
-
-                    // test erroneous calls that check for negative values
-                    Path invalidPath = clientFolder.resolve(getCurrentTestName() + "-invalid");
-                    testInvalidParams(sftp, invalidPath, Utils.resolveRelativeRemotePath(parentPath, invalidPath));
-
-                    // cleanup
-                    sftp.rmdir(dir);
-                }
-            } finally {
-                client.stop();
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            Path targetPath = detectTargetFolder();
+            Path lclSftp = Utils.resolve(targetPath, SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), getCurrentTestName());
+            Utils.deleteRecursive(lclSftp);
+
+            Path parentPath = targetPath.getParent();
+            Path clientFolder = assertHierarchyTargetFolderExists(lclSftp).resolve("client");
+            String dir = Utils.resolveRelativeRemotePath(parentPath, clientFolder);
+
+            try (SftpClient sftp = session.createSftpClient()) {
+                sftp.mkdir(dir);
+
+                uploadAndVerifyFile(sftp, clientFolder, dir, 0, "emptyFile.txt");
+                uploadAndVerifyFile(sftp, clientFolder, dir, 1000, "smallFile.txt");
+                uploadAndVerifyFile(sftp, clientFolder, dir, ByteArrayBuffer.MAX_LEN - 1, "bufferMaxLenMinusOneFile.txt");
+                uploadAndVerifyFile(sftp, clientFolder, dir, ByteArrayBuffer.MAX_LEN, "bufferMaxLenFile.txt");
+                // were chunking not implemented, these would fail. these sizes should invoke our internal chunking mechanism
+                uploadAndVerifyFile(sftp, clientFolder, dir, ByteArrayBuffer.MAX_LEN + 1, "bufferMaxLenPlusOneFile.txt");
+                uploadAndVerifyFile(sftp, clientFolder, dir, (int) (1.5 * ByteArrayBuffer.MAX_LEN), "1point5BufferMaxLenFile.txt");
+                uploadAndVerifyFile(sftp, clientFolder, dir, (2 * ByteArrayBuffer.MAX_LEN) - 1, "2TimesBufferMaxLenMinusOneFile.txt");
+                uploadAndVerifyFile(sftp, clientFolder, dir, 2 * ByteArrayBuffer.MAX_LEN, "2TimesBufferMaxLenFile.txt");
+                uploadAndVerifyFile(sftp, clientFolder, dir, (2 * ByteArrayBuffer.MAX_LEN) + 1, "2TimesBufferMaxLenPlusOneFile.txt");
+                uploadAndVerifyFile(sftp, clientFolder, dir, 200000, "largerFile.txt");
+
+                // test erroneous calls that check for negative values
+                Path invalidPath = clientFolder.resolve(getCurrentTestName() + "-invalid");
+                testInvalidParams(sftp, invalidPath, Utils.resolveRelativeRemotePath(parentPath, invalidPath));
+
+                // cleanup
+                sftp.rmdir(dir);
             }
         }
     }
@@ -903,8 +845,8 @@ public class SftpTest extends AbstractSftpClientTestSupport {
             Vector<?> res = c.ls(path);
             File dir = baseDir.getParentFile();
             Collection<String> expNames = OsUtils.isUNIX()
-                                        ? new LinkedList<String>()
-                                        : new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+                                        ? new LinkedList<>()
+                                        : new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
             String[] names = dir.list();
             if (GenericUtils.length(names) > 0) {
                 for (String n : names) {
@@ -942,123 +884,110 @@ public class SftpTest extends AbstractSftpClientTestSupport {
 
         Path parentPath = targetPath.getParent();
         Path clientFolder = assertHierarchyTargetFolderExists(lclSftp.resolve("client"));
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient()) {
+                Path file1 = clientFolder.resolve("file-1.txt");
+                String file1Path = Utils.resolveRelativeRemotePath(parentPath, file1);
+                try (OutputStream os = sftp.write(file1Path, SftpClient.MIN_WRITE_BUFFER_SIZE)) {
+                    os.write((getCurrentTestName() + "\n").getBytes(StandardCharsets.UTF_8));
+                }
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    Path file1 = clientFolder.resolve("file-1.txt");
-                    String file1Path = Utils.resolveRelativeRemotePath(parentPath, file1);
-                    try (OutputStream os = sftp.write(file1Path, SftpClient.MIN_WRITE_BUFFER_SIZE)) {
-                        os.write((getCurrentTestName() + "\n").getBytes(StandardCharsets.UTF_8));
-                    }
-
-                    Path file2 = clientFolder.resolve("file-2.txt");
-                    String file2Path = Utils.resolveRelativeRemotePath(parentPath, file2);
-                    Path file3 = clientFolder.resolve("file-3.txt");
-                    String file3Path = Utils.resolveRelativeRemotePath(parentPath, file3);
-                    try {
-                        sftp.rename(file2Path, file3Path);
-                        fail("Unxpected rename success of " + file2Path + " => " + file3Path);
-                    } catch (org.apache.sshd.common.subsystem.sftp.SftpException e) {
-                        assertEquals("Mismatched status for failed rename of " + file2Path + " => " + file3Path, SftpConstants.SSH_FX_NO_SUCH_FILE, e.getStatus());
-                    }
-
-                    try (OutputStream os = sftp.write(file2Path, SftpClient.MIN_WRITE_BUFFER_SIZE)) {
-                        os.write("h".getBytes(StandardCharsets.UTF_8));
-                    }
+                Path file2 = clientFolder.resolve("file-2.txt");
+                String file2Path = Utils.resolveRelativeRemotePath(parentPath, file2);
+                Path file3 = clientFolder.resolve("file-3.txt");
+                String file3Path = Utils.resolveRelativeRemotePath(parentPath, file3);
+                try {
+                    sftp.rename(file2Path, file3Path);
+                    fail("Unxpected rename success of " + file2Path + " => " + file3Path);
+                } catch (org.apache.sshd.common.subsystem.sftp.SftpException e) {
+                    assertEquals("Mismatched status for failed rename of " + file2Path + " => " + file3Path, SftpConstants.SSH_FX_NO_SUCH_FILE, e.getStatus());
+                }
 
-                    try {
-                        sftp.rename(file1Path, file2Path);
-                        fail("Unxpected rename success of " + file1Path + " => " + file2Path);
-                    } catch (org.apache.sshd.common.subsystem.sftp.SftpException e) {
-                        assertEquals("Mismatched status for failed rename of " + file1Path + " => " + file2Path, SftpConstants.SSH_FX_FILE_ALREADY_EXISTS, e.getStatus());
-                    }
+                try (OutputStream os = sftp.write(file2Path, SftpClient.MIN_WRITE_BUFFER_SIZE)) {
+                    os.write("h".getBytes(StandardCharsets.UTF_8));
+                }
 
-                    sftp.rename(file1Path, file2Path, SftpClient.CopyMode.Overwrite);
+                try {
+                    sftp.rename(file1Path, file2Path);
+                    fail("Unxpected rename success of " + file1Path + " => " + file2Path);
+                } catch (org.apache.sshd.common.subsystem.sftp.SftpException e) {
+                    assertEquals("Mismatched status for failed rename of " + file1Path + " => " + file2Path, SftpConstants.SSH_FX_FILE_ALREADY_EXISTS, e.getStatus());
                 }
-            } finally {
-                client.stop();
+
+                sftp.rename(file1Path, file2Path, SftpClient.CopyMode.Overwrite);
             }
         }
     }
 
     @Test
     public void testServerExtensionsDeclarations() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient()) {
-                    Map<String, byte[]> extensions = sftp.getServerExtensions();
-                    for (String name : new String[]{
-                        SftpConstants.EXT_NEWLINE, SftpConstants.EXT_VERSIONS,
-                        SftpConstants.EXT_VENDOR_ID, SftpConstants.EXT_ACL_SUPPORTED,
-                        SftpConstants.EXT_SUPPORTED, SftpConstants.EXT_SUPPORTED2
-                    }) {
-                        assertTrue("Missing extension=" + name, extensions.containsKey(name));
-                    }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient()) {
+                Map<String, byte[]> extensions = sftp.getServerExtensions();
+                for (String name : new String[]{
+                    SftpConstants.EXT_NEWLINE, SftpConstants.EXT_VERSIONS,
+                    SftpConstants.EXT_VENDOR_ID, SftpConstants.EXT_ACL_SUPPORTED,
+                    SftpConstants.EXT_SUPPORTED, SftpConstants.EXT_SUPPORTED2
+                }) {
+                    assertTrue("Missing extension=" + name, extensions.containsKey(name));
+                }
 
-                    Map<String, ?> data = ParserUtils.parse(extensions);
-                    for (Map.Entry<String, ?> de : data.entrySet()) {
-                        String extName = de.getKey();
-                        Object extValue = de.getValue();
-                        outputDebugMessage("%s: %s", extName, extValue);
-                        if (SftpConstants.EXT_SUPPORTED.equalsIgnoreCase(extName)) {
-                            assertSupportedExtensions(extName, ((Supported) extValue).extensionNames);
-                        } else if (SftpConstants.EXT_SUPPORTED2.equalsIgnoreCase(extName)) {
-                            assertSupportedExtensions(extName, ((Supported2) extValue).extensionNames);
-                        } else if (SftpConstants.EXT_ACL_SUPPORTED.equalsIgnoreCase(extName)) {
-                            assertSupportedAclCapabilities((AclCapabilities) extValue);
-                        } else if (SftpConstants.EXT_VERSIONS.equalsIgnoreCase(extName)) {
-                            assertSupportedVersions((Versions) extValue);
-                        } else if (SftpConstants.EXT_NEWLINE.equalsIgnoreCase(extName)) {
-                            assertNewlineValue((Newline) extValue);
-                        }
+                Map<String, ?> data = ParserUtils.parse(extensions);
+                for (Map.Entry<String, ?> de : data.entrySet()) {
+                    String extName = de.getKey();
+                    Object extValue = de.getValue();
+                    outputDebugMessage("%s: %s", extName, extValue);
+                    if (SftpConstants.EXT_SUPPORTED.equalsIgnoreCase(extName)) {
+                        assertSupportedExtensions(extName, ((Supported) extValue).extensionNames);
+                    } else if (SftpConstants.EXT_SUPPORTED2.equalsIgnoreCase(extName)) {
+                        assertSupportedExtensions(extName, ((Supported2) extValue).extensionNames);
+                    } else if (SftpConstants.EXT_ACL_SUPPORTED.equalsIgnoreCase(extName)) {
+                        assertSupportedAclCapabilities((AclCapabilities) extValue);
+                    } else if (SftpConstants.EXT_VERSIONS.equalsIgnoreCase(extName)) {
+                        assertSupportedVersions((Versions) extValue);
+                    } else if (SftpConstants.EXT_NEWLINE.equalsIgnoreCase(extName)) {
+                        assertNewlineValue((Newline) extValue);
                     }
+                }
 
-                    for (String extName : extensions.keySet()) {
-                        if (!data.containsKey(extName)) {
-                            outputDebugMessage("No parser for extension=%s", extName);
-                        }
+                for (String extName : extensions.keySet()) {
+                    if (!data.containsKey(extName)) {
+                        outputDebugMessage("No parser for extension=%s", extName);
                     }
+                }
 
-                    for (OpenSSHExtension expected : SftpSubsystem.DEFAULT_OPEN_SSH_EXTENSIONS) {
-                        String name = expected.getName();
-                        Object value = data.get(name);
-                        assertNotNull("OpenSSH extension not declared: " + name, value);
+                for (OpenSSHExtension expected : SftpSubsystem.DEFAULT_OPEN_SSH_EXTENSIONS) {
+                    String name = expected.getName();
+                    Object value = data.get(name);
+                    assertNotNull("OpenSSH extension not declared: " + name, value);
 
-                        OpenSSHExtension actual = (OpenSSHExtension) value;
-                        assertEquals("Mismatched version for OpenSSH extension=" + name, expected.getVersion(), actual.getVersion());
-                    }
+                    OpenSSHExtension actual = (OpenSSHExtension) value;
+                    assertEquals("Mismatched version for OpenSSH extension=" + name, expected.getVersion(), actual.getVersion());
+                }
+
+                for (BuiltinSftpClientExtensions type : BuiltinSftpClientExtensions.VALUES) {
+                    String extensionName = type.getName();
+                    boolean isOpenSSHExtension = extensionName.endsWith("@openssh.com");
+                    SftpClientExtension instance = sftp.getExtension(extensionName);
 
-                    for (BuiltinSftpClientExtensions type : BuiltinSftpClientExtensions.VALUES) {
-                        String extensionName = type.getName();
-                        boolean isOpenSSHExtension = extensionName.endsWith("@openssh.com");
-                        SftpClientExtension instance = sftp.getExtension(extensionName);
-
-                        assertNotNull("Extension not implemented:" + extensionName, instance);
-                        assertEquals("Mismatched instance name", extensionName, instance.getName());
-
-                        if (instance.isSupported()) {
-                            if (isOpenSSHExtension) {
-                                assertTrue("Unlisted default OpenSSH extension: " + extensionName, SftpSubsystem.DEFAULT_OPEN_SSH_EXTENSIONS_NAMES.contains(extensionName));
-                            }
-                        } else {
-                            assertTrue("Unsupported non-OpenSSH extension: " + extensionName, isOpenSSHExtension);
-                            assertFalse("Unsupported default OpenSSH extension: " + extensionName, SftpSubsystem.DEFAULT_OPEN_SSH_EXTENSIONS_NAMES.contains(extensionName));
+                    assertNotNull("Extension not implemented:" + extensionName, instance);
+                    assertEquals("Mismatched instance name", extensionName, instance.getName());
+
+                    if (instance.isSupported()) {
+                        if (isOpenSSHExtension) {
+                            assertTrue("Unlisted default OpenSSH extension: " + extensionName, SftpSubsystem.DEFAULT_OPEN_SSH_EXTENSIONS_NAMES.contains(extensionName));
                         }
+                    } else {
+                        assertTrue("Unsupported non-OpenSSH extension: " + extensionName, isOpenSSHExtension);
+                        assertFalse("Unsupported default OpenSSH extension: " + extensionName, SftpSubsystem.DEFAULT_OPEN_SSH_EXTENSIONS_NAMES.contains(extensionName));
                     }
                 }
-            } finally {
-                client.stop();
             }
         }
     }
@@ -1129,43 +1058,37 @@ public class SftpTest extends AbstractSftpClientTestSupport {
             }
         };
 
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-                try (SftpClient sftp = session.createSftpClient(selector)) {
-                    assertEquals("Mismatched negotiated version", selected.get(), sftp.getVersion());
-                    testClient(client, sftp);
-                }
-            } finally {
-                client.stop();
+            try (SftpClient sftp = session.createSftpClient(selector)) {
+                assertEquals("Mismatched negotiated version", selected.get(), sftp.getVersion());
+                testClient(client, sftp);
             }
         }
     }
 
     @Test   // see SSHD-621
     public void testServerDoesNotSupportSftp() throws Exception {
-        sshd.setSubsystemFactories(null);
-
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+        List<NamedFactory<Command>> factories = sshd.getSubsystemFactories();
+        assertEquals("Mismatched subsystem factories count", 1, GenericUtils.size(factories));
 
-                PropertyResolverUtils.updateProperty(session, SftpClient.SFTP_CHANNEL_OPEN_TIMEOUT, TimeUnit.SECONDS.toMillis(4L));
-                try (SftpClient sftp = session.createSftpClient()) {
-                    fail("Unexpected SFTP client creation success");
-                } catch (SocketTimeoutException | EOFException | WindowClosedException e) {
-                    // expected - ignored
-                }
+        sshd.setSubsystemFactories(null);
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            PropertyResolverUtils.updateProperty(session, SftpClient.SFTP_CHANNEL_OPEN_TIMEOUT, TimeUnit.SECONDS.toMillis(4L));
+            try (SftpClient sftp = session.createSftpClient()) {
+                fail("Unexpected SFTP client creation success");
+            } catch (SocketTimeoutException | EOFException | WindowClosedException e) {
+                // expected - ignored
             } finally {
-                client.stop();
+                PropertyResolverUtils.updateProperty(session, SftpClient.SFTP_CHANNEL_OPEN_TIMEOUT, SftpClient.DEFAULT_CHANNEL_OPEN_TIMEOUT);
             }
+        } finally {
+            sshd.setSubsystemFactories(factories);
         }
     }
 
@@ -1177,10 +1100,9 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         Path parentPath = targetPath.getParent();
         Path clientFolder = assertHierarchyTargetFolderExists(lclSftp).resolve("client");
         String dir = Utils.resolveRelativeRemotePath(parentPath, clientFolder);
-        String file = dir + "/" + "file.txt";
-
         sftp.mkdir(dir);
 
+        String file = dir + "/" + getCurrentTestName() + "-file.txt";
         try (SftpClient.CloseableHandle h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write, SftpClient.OpenMode.Create))) {
             byte[] d = "0123456789\n".getBytes(StandardCharsets.UTF_8);
             sftp.write(h, 0, d, 0, d.length);
@@ -1191,20 +1113,18 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         }
 
         try (SftpClient.CloseableHandle h = sftp.openDir(dir)) {
-            List<SftpClient.DirEntry> dirEntries = sftp.readDir(h);
-            assertNotNull("No dir entries", dirEntries);
-
+            List<SftpClient.DirEntry> dirEntries = new ArrayList<>();
             boolean dotFiltered = false;
             boolean dotdotFiltered = false;
-            for (Iterator<SftpClient.DirEntry> it = dirEntries.iterator(); it.hasNext();) {
-                SftpClient.DirEntry entry = it.next();
+            for (SftpClient.DirEntry entry : sftp.listDir(h)) {
                 String name = entry.getFilename();
+                outputDebugMessage("readDir(%s) initial file: %s", dir, name);
                 if (".".equals(name) && (!dotFiltered)) {
-                    it.remove();
                     dotFiltered = true;
                 } else if ("..".equals(name) && (!dotdotFiltered)) {
-                    it.remove();
                     dotdotFiltered = true;
+                } else {
+                    dirEntries.add(entry);
                 }
             }
 
@@ -1247,6 +1167,8 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         for (SftpClient.DirEntry entry : sftp.readDir(dir)) {
             assertNotNull("Unexpected null entry", entry);
             String name = entry.getFilename();
+            outputDebugMessage("readDir(%s) overwritten file: %s", dir, name);
+
             if (".".equals(name) && (!dotFiltered)) {
                 dotFiltered = true;
             } else if ("..".equals(name) && (!dotdotFiltered)) {
@@ -1258,9 +1180,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         assertTrue("Dot entry not read", dotFiltered);
         assertTrue("Dot-dot entry not read", dotdotFiltered);
         assertEquals("Mismatched read dir entries", 1, nb);
-
         sftp.remove(file);
-
         sftp.rmdir(dir);
     }
 
@@ -1276,7 +1196,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
 
         SftpSubsystemFactory factory = (SftpSubsystemFactory) f;
         final AtomicReference<LinkData> linkDataHolder = new AtomicReference<>();
-        factory.addSftpEventListener(new AbstractSftpEventListenerAdapter() {
+        SftpEventListener listener = new AbstractSftpEventListenerAdapter() {
             @Override
             public void linking(ServerSession session, Path src, Path target, boolean symLink) {
                 assertNull("Multiple linking calls", linkDataHolder.getAndSet(new LinkData(src, target, symLink)));
@@ -1291,7 +1211,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
                 assertEquals("Mismatched link type", data.isSymLink(), symLink);
                 assertNull("Unexpected failure", thrown);
             }
-        });
+        };
 
         Path targetPath = detectTargetFolder();
         Path lclSftp = Utils.resolve(targetPath, SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), getCurrentTestName());
@@ -1313,35 +1233,41 @@ public class SftpTest extends AbstractSftpClientTestSupport {
         Path sourcePath = assertHierarchyTargetFolderExists(lclSftp).resolve("src.txt");
         String remSrcPath = "/" + Utils.resolveRelativeRemotePath(parentPath, sourcePath);
 
-        String data = getCurrentTestName();
-        ChannelSftp c = (ChannelSftp) session.openChannel(SftpConstants.SFTP_SUBSYSTEM_NAME);
-        c.connect();
+        factory.addSftpEventListener(listener);
         try {
-            try (InputStream dataStream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8))) {
-                c.put(dataStream, remSrcPath);
-            }
-            assertTrue("Source file not created: " + sourcePath, Files.exists(sourcePath));
-            assertEquals("Mismatched stored data in " + remSrcPath, data, readFile(remSrcPath));
-
-            Path linkPath = lclSftp.resolve("link-" + sourcePath.getFileName());
-            String remLinkPath = "/" + Utils.resolveRelativeRemotePath(parentPath, linkPath);
-            LinkOption[] options = IoUtils.getLinkOptions(false);
-            if (Files.exists(linkPath, options)) {
-                Files.delete(linkPath);
-            }
-            assertFalse("Target link exists before linking: " + linkPath, Files.exists(linkPath, options));
+            String data = getCurrentTestName();
+            ChannelSftp c = (ChannelSftp) session.openChannel(SftpConstants.SFTP_SUBSYSTEM_NAME);
+            c.connect();
 
-            outputDebugMessage("Symlink %s => %s", remLinkPath, remSrcPath);
-            c.symlink(remSrcPath, remLinkPath);
+            try {
+                try (InputStream dataStream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8))) {
+                    c.put(dataStream, remSrcPath);
+                }
+                assertTrue("Source file not created: " + sourcePath, Files.exists(sourcePath));
+                assertEquals("Mismatched stored data in " + remSrcPath, data, readFile(remSrcPath));
+
+                Path linkPath = lclSftp.resolve("link-" + sourcePath.getFileName());
+                String remLinkPath = "/" + Utils.resolveRelativeRemotePath(parentPath, linkPath);
+                LinkOption[] options = IoUtils.getLinkOptions(false);
+                if (Files.exists(linkPath, options)) {
+                    Files.delete(linkPath);
+                }
+                assertFalse("Target link exists before linking: " + linkPath, Files.exists(linkPath, options));
+
+                outputDebugMessage("Symlink %s => %s", remLinkPath, remSrcPath);
+                c.symlink(remSrcPath, remLinkPath);
 
-            assertTrue("Symlink not created: " + linkPath, Files.exists(linkPath, options));
-            assertEquals("Mismatched link data in " + remLinkPath, data, readFile(remLinkPath));
+                assertTrue("Symlink not created: " + linkPath, Files.exists(linkPath, options));
+                assertEquals("Mismatched link data in " + remLinkPath, data, readFile(remLinkPath));
 
-            String str1 = c.readlink(remLinkPath);
-            String str2 = c.realpath(remSrcPath);
-            assertEquals("Mismatched link vs. real path", str1, str2);
+                String str1 = c.readlink(remLinkPath);
+                String str2 = c.realpath(remSrcPath);
+                assertEquals("Mismatched link vs. real path", str1, str2);
+            } finally {
+                c.disconnect();
+            }
         } finally {
-            c.disconnect();
+            factory.removeSftpEventListener(listener);
         }
 
         assertNotNull("No symlink signalled", linkDataHolder.getAndSet(null));

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ae8d1c99/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpVersionsTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpVersionsTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpVersionsTest.java
index ab9d74c..0da39a9 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpVersionsTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpVersionsTest.java
@@ -40,7 +40,6 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
-import org.apache.sshd.client.SshClient;
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.client.subsystem.sftp.SftpClient.Attributes;
 import org.apache.sshd.client.subsystem.sftp.SftpClient.CloseableHandle;
@@ -57,7 +56,6 @@ import org.apache.sshd.server.subsystem.sftp.SftpEventListener;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystem;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
 import org.apache.sshd.util.test.Utils;
-import org.junit.After;
 import org.junit.Before;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -99,29 +97,18 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport {
         setupServer();
     }
 
-    @After
-    public void tearDown() throws Exception {
-        tearDownServer();
-    }
-
     public final int getTestedVersion() {
         return testVersion;
     }
 
     @Test
     public void testSftpVersionSelector() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
 
-                try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
-                    assertEquals("Mismatched negotiated version", getTestedVersion(), sftp.getVersion());
-                }
-            } finally {
-                client.stop();
+            try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
+                assertEquals("Mismatched negotiated version", getTestedVersion(), sftp.getVersion());
             }
         }
     }
@@ -134,35 +121,28 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport {
         Files.write(lclFile, getClass().getName().getBytes(StandardCharsets.UTF_8));
         Path parentPath = targetPath.getParent();
         String remotePath = Utils.resolveRelativeRemotePath(parentPath, lclFile);
-
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
-                    Attributes attrs = sftp.lstat(remotePath);
-                    long expectedSeconds = TimeUnit.SECONDS.convert(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1L), TimeUnit.MILLISECONDS);
-                    attrs.getFlags().clear();
-                    attrs.modifyTime(expectedSeconds);
-                    sftp.setStat(remotePath, attrs);
-
-                    attrs = sftp.lstat(remotePath);
-                    long actualSeconds = attrs.getModifyTime().to(TimeUnit.SECONDS);
-                    // The NTFS file system delays updates to the last access time for a file by up to 1 hour after the last access
-                    if (expectedSeconds != actualSeconds) {
-                        System.err.append("Mismatched last modified time for ").append(lclFile.toString())
-                                  .append(" - expected=").append(String.valueOf(expectedSeconds))
-                                  .append('[').append(new Date(TimeUnit.SECONDS.toMillis(expectedSeconds)).toString()).append(']')
-                                  .append(", actual=").append(String.valueOf(actualSeconds))
-                                  .append('[').append(new Date(TimeUnit.SECONDS.toMillis(actualSeconds)).toString()).append(']')
-                                  .println();
-                    }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
+                Attributes attrs = sftp.lstat(remotePath);
+                long expectedSeconds = TimeUnit.SECONDS.convert(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1L), TimeUnit.MILLISECONDS);
+                attrs.getFlags().clear();
+                attrs.modifyTime(expectedSeconds);
+                sftp.setStat(remotePath, attrs);
+
+                attrs = sftp.lstat(remotePath);
+                long actualSeconds = attrs.getModifyTime().to(TimeUnit.SECONDS);
+                // The NTFS file system delays updates to the last access time for a file by up to 1 hour after the last access
+                if (expectedSeconds != actualSeconds) {
+                    System.err.append("Mismatched last modified time for ").append(lclFile.toString())
+                              .append(" - expected=").append(String.valueOf(expectedSeconds))
+                              .append('[').append(new Date(TimeUnit.SECONDS.toMillis(expectedSeconds)).toString()).append(']')
+                              .append(", actual=").append(String.valueOf(actualSeconds))
+                              .append('[').append(new Date(TimeUnit.SECONDS.toMillis(actualSeconds)).toString()).append(']')
+                              .println();
                 }
-            } finally {
-                client.stop();
             }
         }
     }
@@ -179,32 +159,26 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport {
 
         Path parentPath = targetPath.getParent();
         String remotePath = Utils.resolveRelativeRemotePath(parentPath, lclSftp);
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
-                    for (DirEntry entry : sftp.readDir(remotePath)) {
-                        String fileName = entry.getFilename();
-                        if (".".equals(fileName) || "..".equals(fileName)) {
-                            continue;
-                        }
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
+                for (DirEntry entry : sftp.readDir(remotePath)) {
+                    String fileName = entry.getFilename();
+                    if (".".equals(fileName) || "..".equals(fileName)) {
+                        continue;
+                    }
 
-                        Attributes attrs = validateSftpFileTypeAndPermissions(fileName, getTestedVersion(), entry.getAttributes());
-                        if (subFolderName.equals(fileName)) {
-                            assertEquals("Mismatched sub-folder type", SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY, attrs.getType());
-                            assertTrue("Sub-folder not marked as directory", attrs.isDirectory());
-                        } else if (lclFileName.equals(fileName)) {
-                            assertEquals("Mismatched sub-file type", SftpConstants.SSH_FILEXFER_TYPE_REGULAR, attrs.getType());
-                            assertTrue("Sub-folder not marked as directory", attrs.isRegularFile());
-                        }
+                    Attributes attrs = validateSftpFileTypeAndPermissions(fileName, getTestedVersion(), entry.getAttributes());
+                    if (subFolderName.equals(fileName)) {
+                        assertEquals("Mismatched sub-folder type", SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY, attrs.getType());
+                        assertTrue("Sub-folder not marked as directory", attrs.isDirectory());
+                    } else if (lclFileName.equals(fileName)) {
+                        assertEquals("Mismatched sub-file type", SftpConstants.SSH_FILEXFER_TYPE_REGULAR, attrs.getType());
+                        assertTrue("Sub-folder not marked as directory", attrs.isRegularFile());
                     }
                 }
-            } finally {
-                client.stop();
             }
         }
     }
@@ -231,7 +205,7 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport {
                     protected Map<String, Object> resolveFileAttributes(Path file, int flags, LinkOption... options) throws IOException {
                         Map<String, Object> attrs = super.resolveFileAttributes(file, flags, options);
                         if (GenericUtils.isEmpty(attrs)) {
-                            attrs = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER);
+                            attrs = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
                         }
 
                         @SuppressWarnings("unchecked")
@@ -285,8 +259,6 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport {
             }
         });
 
-        sshd.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(factory));
-
         Path targetPath = detectTargetFolder();
         Path lclSftp = Utils.resolve(targetPath, SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName());
         Files.createDirectories(lclSftp.resolve("sub-folder"));
@@ -296,39 +268,38 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport {
         Path parentPath = targetPath.getParent();
         String remotePath = Utils.resolveRelativeRemotePath(parentPath, lclSftp);
         int numInvoked = 0;
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
-                    for (DirEntry entry : sftp.readDir(remotePath)) {
-                        String fileName = entry.getFilename();
-                        if (".".equals(fileName) || "..".equals(fileName)) {
-                            continue;
-                        }
 
-                        Attributes attrs = validateSftpFileTypeAndPermissions(fileName, getTestedVersion(), entry.getAttributes());
-                        List<AclEntry> aclActual = attrs.getAcl();
-                        if (getTestedVersion() == SftpConstants.SFTP_V3) {
-                            assertNull("Unexpected ACL for entry=" + fileName, aclActual);
-                        } else {
-                            assertListEquals("Mismatched ACL for entry=" + fileName, aclExpected, aclActual);
-                        }
+        List<NamedFactory<Command>> factories = sshd.getSubsystemFactories();
+        sshd.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(factory));
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
+                for (DirEntry entry : sftp.readDir(remotePath)) {
+                    String fileName = entry.getFilename();
+                    if (".".equals(fileName) || "..".equals(fileName)) {
+                        continue;
+                    }
 
-                        attrs.getFlags().clear();
-                        attrs.setAcl(aclExpected);
-                        sftp.setStat(remotePath + "/" + fileName, attrs);
-                        if (getTestedVersion() > SftpConstants.SFTP_V3) {
-                            numInvoked++;
-                        }
+                    Attributes attrs = validateSftpFileTypeAndPermissions(fileName, getTestedVersion(), entry.getAttributes());
+                    List<AclEntry> aclActual = attrs.getAcl();
+                    if (getTestedVersion() == SftpConstants.SFTP_V3) {
+                        assertNull("Unexpected ACL for entry=" + fileName, aclActual);
+                    } else {
+                        assertListEquals("Mismatched ACL for entry=" + fileName, aclExpected, aclActual);
+                    }
+
+                    attrs.getFlags().clear();
+                    attrs.setAcl(aclExpected);
+                    sftp.setStat(remotePath + "/" + fileName, attrs);
+                    if (getTestedVersion() > SftpConstants.SFTP_V3) {
+                        numInvoked++;
                     }
                 }
-            } finally {
-                client.stop();
             }
+        } finally {
+            sshd.setSubsystemFactories(factories);
         }
 
         assertEquals("Mismatched invocations count", numInvoked, numInvocations.get());
@@ -356,7 +327,7 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport {
                     protected Map<String, Object> resolveFileAttributes(Path file, int flags, LinkOption... options) throws IOException {
                         Map<String, Object> attrs = super.resolveFileAttributes(file, flags, options);
                         if (GenericUtils.isEmpty(attrs)) {
-                            attrs = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER);
+                            attrs = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
                         }
 
                         @SuppressWarnings("unchecked")
@@ -408,7 +379,6 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport {
             }
         });
 
-        sshd.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(factory));
         Path targetPath = detectTargetFolder();
         Path lclSftp = Utils.resolve(targetPath, SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName());
         Files.createDirectories(lclSftp.resolve("sub-folder"));
@@ -418,32 +388,31 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport {
         Path parentPath = targetPath.getParent();
         String remotePath = Utils.resolveRelativeRemotePath(parentPath, lclSftp);
         int numInvoked = 0;
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
-                    for (DirEntry entry : sftp.readDir(remotePath)) {
-                        String fileName = entry.getFilename();
-                        if (".".equals(fileName) || "..".equals(fileName)) {
-                            continue;
-                        }
 
-                        Attributes attrs = validateSftpFileTypeAndPermissions(fileName, getTestedVersion(), entry.getAttributes());
-                        Map<String, byte[]> actExtensions = attrs.getExtensions();
-                        assertExtensionsMapEquals("dirEntry=" + fileName, expExtensions, actExtensions);
-                        attrs.getFlags().clear();
-                        attrs.setStringExtensions(expExtensions);
-                        sftp.setStat(remotePath + "/" + fileName, attrs);
-                        numInvoked++;
+        List<NamedFactory<Command>> factories = sshd.getSubsystemFactories();
+        sshd.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(factory));
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
+                for (DirEntry entry : sftp.readDir(remotePath)) {
+                    String fileName = entry.getFilename();
+                    if (".".equals(fileName) || "..".equals(fileName)) {
+                        continue;
                     }
+
+                    Attributes attrs = validateSftpFileTypeAndPermissions(fileName, getTestedVersion(), entry.getAttributes());
+                    Map<String, byte[]> actExtensions = attrs.getExtensions();
+                    assertExtensionsMapEquals("dirEntry=" + fileName, expExtensions, actExtensions);
+                    attrs.getFlags().clear();
+                    attrs.setStringExtensions(expExtensions);
+                    sftp.setStat(remotePath + "/" + fileName, attrs);
+                    numInvoked++;
                 }
-            } finally {
-                client.stop();
             }
+        } finally {
+            sshd.setSubsystemFactories(factories);
         }
 
         assertEquals("Mismatched invocations count", numInvoked, numInvocations.get());
@@ -451,48 +420,42 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport {
 
     @Test   // see SSHD-623
     public void testEndOfListIndicator() throws Exception {
-        try (SshClient client = setupTestClient()) {
-            client.start();
-
-            try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-                session.addPasswordIdentity(getCurrentTestName());
-                session.auth().verify(5L, TimeUnit.SECONDS);
-
-                try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
-                    AtomicReference<Boolean> eolIndicator = new AtomicReference<>();
-                    int version = sftp.getVersion();
-                    Path targetPath = detectTargetFolder();
-                    Path parentPath = targetPath.getParent();
-                    String remotePath = Utils.resolveRelativeRemotePath(parentPath, targetPath);
-
-                    try (CloseableHandle handle = sftp.openDir(remotePath)) {
-                        List<DirEntry> entries = sftp.readDir(handle, eolIndicator);
-                        for (int index = 1; entries != null; entries = sftp.readDir(handle, eolIndicator), index++) {
-                            Boolean value = eolIndicator.get();
-                            if (version < SftpConstants.SFTP_V6) {
-                                assertNull("Unexpected indicator value at iteration #" + index, value);
-                            } else {
-                                assertNotNull("No indicator returned at iteration #" + index, value);
-                                if (value.booleanValue()) {
-                                    break;
-                                }
-                            }
-                            eolIndicator.set(null);    // make sure starting fresh
-                        }
-
+        try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient(getTestedVersion())) {
+                AtomicReference<Boolean> eolIndicator = new AtomicReference<>();
+                int version = sftp.getVersion();
+                Path targetPath = detectTargetFolder();
+                Path parentPath = targetPath.getParent();
+                String remotePath = Utils.resolveRelativeRemotePath(parentPath, targetPath);
+
+                try (CloseableHandle handle = sftp.openDir(remotePath)) {
+                    List<DirEntry> entries = sftp.readDir(handle, eolIndicator);
+                    for (int index = 1; entries != null; entries = sftp.readDir(handle, eolIndicator), index++) {
                         Boolean value = eolIndicator.get();
                         if (version < SftpConstants.SFTP_V6) {
-                            assertNull("Unexpected end-of-list indication received at end of entries", value);
-                            assertNull("Unexpected no last entries indication", entries);
+                            assertNull("Unexpected indicator value at iteration #" + index, value);
                         } else {
-                            assertNotNull("No end-of-list indication received at end of entries", value);
-                            assertNotNull("No last received entries", entries);
-                            assertTrue("Bad end-of-list value", value.booleanValue());
+                            assertNotNull("No indicator returned at iteration #" + index, value);
+                            if (value.booleanValue()) {
+                                break;
+                            }
                         }
+                        eolIndicator.set(null);    // make sure starting fresh
+                    }
+
+                    Boolean value = eolIndicator.get();
+                    if (version < SftpConstants.SFTP_V6) {
+                        assertNull("Unexpected end-of-list indication received at end of entries", value);
+                        assertNull("Unexpected no last entries indication", entries);
+                    } else {
+                        assertNotNull("No end-of-list indication received at end of entries", value);
+                        assertNotNull("No last received entries", entries);
+                        assertTrue("Bad end-of-list value", value.booleanValue());
                     }
                 }
-            } finally {
-                client.stop();
             }
         }
     }