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 2015/12/08 06:12:14 UTC

[1/2] mina-sshd git commit: Using a semaphore in order to attempt and coordinate the various KeyReExchangeTest(s)

Repository: mina-sshd
Updated Branches:
  refs/heads/master 6f956abf4 -> 53055cb53


Using a semaphore in order to attempt and coordinate the various KeyReExchangeTest(s)


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

Branch: refs/heads/master
Commit: 902280870d80a59e4f8c1818295be6c47475ac4f
Parents: 6f956ab
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Tue Dec 8 07:09:46 2015 +0200
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Tue Dec 8 07:09:46 2015 +0200

----------------------------------------------------------------------
 .../java/org/apache/sshd/KeyReExchangeTest.java | 92 ++++++++++++++++++--
 1 file changed, 84 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/90228087/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
index fd006b7..34d1a40 100644
--- a/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
@@ -31,6 +31,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -122,6 +123,7 @@ public class KeyReExchangeTest extends BaseTestSupport {
                 session.addPasswordIdentity(getCurrentTestName());
                 session.auth().verify(5L, TimeUnit.SECONDS);
 
+                outputDebugMessage("Request switch to none cipher for %s", session);
                 KeyExchangeFuture switchFuture = session.switchToNoneCipher();
                 switchFuture.verify(5L, TimeUnit.SECONDS);
                 try (ClientChannel channel = session.createSubsystemChannel(SftpConstants.SFTP_SUBSYSTEM_NAME)) {
@@ -232,6 +234,8 @@ public class KeyReExchangeTest extends BaseTestSupport {
                     int len = is.read(data);
                     String str = new String(data, 0, len);
                     assertEquals("Mismatched data at iteration " + i, expected, str);
+
+                    outputDebugMessage("Request re-key #%d", i);
                     s.rekey();
                 }
             } finally {
@@ -253,12 +257,25 @@ public class KeyReExchangeTest extends BaseTestSupport {
                 session.addPasswordIdentity(getCurrentTestName());
                 session.auth().verify(5L, TimeUnit.SECONDS);
 
+                final Semaphore pipedCount = new Semaphore(0, true);
                 try (ChannelShell channel = session.createShellChannel();
                      ByteArrayOutputStream sent = new ByteArrayOutputStream();
                      PipedOutputStream pipedIn = new PipedOutputStream();
                      InputStream inPipe = new PipedInputStream(pipedIn);
                      OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
-                     ByteArrayOutputStream out = new ByteArrayOutputStream();
+                     ByteArrayOutputStream out = new ByteArrayOutputStream() {
+                         @Override
+                         public void write(int b) {
+                             super.write(b);
+                             pipedCount.release(1);
+                         }
+
+                         @Override
+                         public void write(byte[] b, int off, int len) {
+                             super.write(b, off, len);
+                             pipedCount.release(len);
+                         }
+                     };
                      ByteArrayOutputStream err = new ByteArrayOutputStream()) {
 
                     channel.setIn(inPipe);
@@ -290,7 +307,13 @@ public class KeyReExchangeTest extends BaseTestSupport {
                     Collection<ClientChannel.ClientChannelEvent> result =
                             channel.waitFor(EnumSet.of(ClientChannel.ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(15L));
                     assertFalse("Timeout while waiting for channel closure", result.contains(ClientChannel.ClientChannelEvent.TIMEOUT));
-                    assertArrayEquals("Mismatched sent data content", sent.toByteArray(), out.toByteArray());
+
+                    byte[] expected = sent.toByteArray();
+                    if (!pipedCount.tryAcquire(expected.length, 13L, TimeUnit.SECONDS)) {
+                        fail("Failed to await sent data signal for len=" + expected.length + " (available=" + pipedCount.availablePermits() + ")");
+                    }
+
+                    assertArrayEquals("Mismatched sent data content", expected, out.toByteArray());
                 }
             } finally {
                 client.stop();
@@ -306,12 +329,26 @@ public class KeyReExchangeTest extends BaseTestSupport {
         try (SshClient client = setupTestClient()) {
             client.start();
 
+            final Semaphore pipedCount = new Semaphore(0, true);
             try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession();
                  ByteArrayOutputStream sent = new ByteArrayOutputStream();
-                 ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+                 ByteArrayOutputStream out = new ByteArrayOutputStream() {
+                     @Override
+                     public void write(int b) {
+                         super.write(b);
+                         pipedCount.release(1);
+                     }
+
+                     @Override
+                     public void write(byte[] b, int off, int len) {
+                         super.write(b, off, len);
+                         pipedCount.release(len);
+                     }
+                 }) {
                 session.addPasswordIdentity(getCurrentTestName());
                 session.auth().verify(5L, TimeUnit.SECONDS);
 
+                byte[] sentData;
                 try (ChannelShell channel = session.createShellChannel();
                      PipedOutputStream pipedIn = new PipedOutputStream();
                      OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
@@ -371,10 +408,13 @@ public class KeyReExchangeTest extends BaseTestSupport {
                             channel.waitFor(EnumSet.of(ClientChannel.ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(15L));
                     assertFalse("Timeout while waiting for channel closure", result.contains(ClientChannel.ClientChannelEvent.TIMEOUT));
 
+                    sentData = sent.toByteArray();
+                    if (!pipedCount.tryAcquire(sentData.length, 13L, TimeUnit.SECONDS)) {
+                        fail("Failed to await sent data signal for len=" + sentData.length + " (available=" + pipedCount.availablePermits() + ")");
+                    }
                     assertTrue("Expected rekeying", exchanges.get() > 0);
                 }
 
-                byte[] sentData = sent.toByteArray();
                 byte[] outData = out.toByteArray();
                 assertEquals("Mismatched sent data length", sentData.length, outData.length);
                 assertArrayEquals("Mismatched sent data content", sentData, outData);
@@ -392,12 +432,26 @@ public class KeyReExchangeTest extends BaseTestSupport {
         try (SshClient client = setupTestClient()) {
             client.start();
 
+            final Semaphore pipedCount = new Semaphore(0, true);
             try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession();
                  ByteArrayOutputStream sent = new ByteArrayOutputStream();
-                 ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+                 ByteArrayOutputStream out = new ByteArrayOutputStream() {
+                     @Override
+                     public void write(int b) {
+                         super.write(b);
+                         pipedCount.release(1);
+                     }
+
+                     @Override
+                     public void write(byte[] b, int off, int len) {
+                         super.write(b, off, len);
+                         pipedCount.release(len);
+                     }
+                 }) {
                 session.addPasswordIdentity(getCurrentTestName());
                 session.auth().verify(5L, TimeUnit.SECONDS);
 
+                byte[] sentData;
                 try (ChannelShell channel = session.createShellChannel();
                      PipedOutputStream pipedIn = new PipedOutputStream();
                      OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
@@ -474,10 +528,14 @@ public class KeyReExchangeTest extends BaseTestSupport {
                             channel.waitFor(EnumSet.of(ClientChannel.ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(15L));
                     assertFalse("Timeout while waiting for channel closure", result.contains(ClientChannel.ClientChannelEvent.TIMEOUT));
 
+                    sentData = sent.toByteArray();
+                    if (!pipedCount.tryAcquire(sentData.length, 13L, TimeUnit.SECONDS)) {
+                        fail("Failed to await sent data signal for len=" + sentData.length + " (available=" + pipedCount.availablePermits() + ")");
+                    }
+
                     assertTrue("Expected rekeying", exchanges.get() > 0);
                 }
 
-                byte[] sentData = sent.toByteArray();
                 byte[] outData = out.toByteArray();
                 assertEquals("Mismatched sent data length", sentData.length, outData.length);
                 assertArrayEquals("Mismatched sent data content", sentData, outData);
@@ -495,12 +553,26 @@ public class KeyReExchangeTest extends BaseTestSupport {
         try (SshClient client = setupTestClient()) {
             client.start();
 
+            final Semaphore pipedCount = new Semaphore(0, true);
             try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession();
                  ByteArrayOutputStream sent = new ByteArrayOutputStream();
-                 ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+                 ByteArrayOutputStream out = new ByteArrayOutputStream() {
+                     @Override
+                     public void write(int b) {
+                         super.write(b);
+                         pipedCount.release(1);
+                     }
+
+                     @Override
+                     public void write(byte[] b, int off, int len) {
+                         super.write(b, off, len);
+                         pipedCount.release(len);
+                     }
+                 }) {
                 session.addPasswordIdentity(getCurrentTestName());
                 session.auth().verify(5L, TimeUnit.SECONDS);
 
+                byte[] sentData;
                 try (ChannelShell channel = session.createShellChannel();
                      PipedOutputStream pipedIn = new PipedOutputStream();
                      OutputStream sentTracker = new OutputCountTrackingOutputStream(sent) {
@@ -572,10 +644,14 @@ public class KeyReExchangeTest extends BaseTestSupport {
                             channel.waitFor(EnumSet.of(ClientChannel.ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(15L));
                     assertFalse("Timeout while waiting for channel closure", result.contains(ClientChannel.ClientChannelEvent.TIMEOUT));
 
+                    sentData = sent.toByteArray();
+                    if (!pipedCount.tryAcquire(sentData.length, 13L, TimeUnit.SECONDS)) {
+                        fail("Failed to await sent data signal for len=" + sentData.length + " (available=" + pipedCount.availablePermits() + ")");
+                    }
+
                     assertTrue("Expected rekeying", exchanges.get() > 0);
                 }
 
-                byte[] sentData = sent.toByteArray();
                 byte[] outData = out.toByteArray();
                 assertEquals("Mismatched sent data length", sentData.length, outData.length);
                 assertArrayEquals("Mismatched sent data content", sentData, outData);


[2/2] mina-sshd git commit: [SSHD-609] Session does not disconnect if unknown compression factory requested

Posted by lg...@apache.org.
[SSHD-609] Session does not disconnect if unknown compression factory requested


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

Branch: refs/heads/master
Commit: 53055cb5330220d16681f8c94ca920b5130f3802
Parents: 9022808
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Tue Dec 8 07:12:02 2015 +0200
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Tue Dec 8 07:12:02 2015 +0200

----------------------------------------------------------------------
 .../common/compression/BaseCompression.java     |   5 +
 .../common/compression/BuiltinCompressions.java |  22 ++-
 .../sshd/common/compression/Compression.java    |  12 +-
 .../common/compression/CompressionFactory.java  |   2 +-
 .../compression/CompressionInformation.java     |  42 ++++++
 .../common/compression/CompressionNone.java     |  76 ++++++++++
 .../common/config/CompressionConfigValue.java   |  10 ++
 .../sshd/common/session/AbstractSession.java    |  51 +++++--
 .../org/apache/sshd/common/session/Session.java |  33 +++++
 .../compression/BuiltinCompressionsTest.java    |   1 -
 .../java/org/apache/sshd/server/ServerTest.java | 140 ++++++++++++++++---
 .../org/apache/sshd/server/SshServerTest.java   |   3 +
 12 files changed, 350 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/main/java/org/apache/sshd/common/compression/BaseCompression.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/compression/BaseCompression.java b/sshd-core/src/main/java/org/apache/sshd/common/compression/BaseCompression.java
index 7feda60..ff31947 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/compression/BaseCompression.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/compression/BaseCompression.java
@@ -37,6 +37,11 @@ public abstract class BaseCompression implements Compression {
     }
 
     @Override
+    public boolean isCompressionExecuted() {
+        return true;
+    }
+
+    @Override
     public String toString() {
         return getName();
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java b/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
index f0a55c9..43213d8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
@@ -42,7 +42,12 @@ public enum BuiltinCompressions implements CompressionFactory {
     none(Constants.NONE) {
         @Override
         public Compression create() {
-            return null;
+            return new CompressionNone();
+        }
+
+        @Override
+        public boolean isCompressionExecuted() {
+            return false;
         }
     },
     zlib(Constants.ZLIB) {
@@ -56,6 +61,11 @@ public enum BuiltinCompressions implements CompressionFactory {
         public Compression create() {
             return new CompressionDelayedZlib();
         }
+
+        @Override
+        public boolean isDelayed() {
+            return true;
+        }
     };
 
     public static final Set<BuiltinCompressions> VALUES =
@@ -76,6 +86,16 @@ public enum BuiltinCompressions implements CompressionFactory {
     }
 
     @Override
+    public boolean isDelayed() {
+        return false;
+    }
+
+    @Override
+    public boolean isCompressionExecuted() {
+        return true;
+    }
+
+    @Override
     public final String toString() {
         return getName();
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/main/java/org/apache/sshd/common/compression/Compression.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/compression/Compression.java b/sshd-core/src/main/java/org/apache/sshd/common/compression/Compression.java
index 33f6fb2..0f1f809 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/compression/Compression.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/compression/Compression.java
@@ -20,7 +20,6 @@ package org.apache.sshd.common.compression;
 
 import java.io.IOException;
 
-import org.apache.sshd.common.NamedResource;
 import org.apache.sshd.common.util.buffer.Buffer;
 
 /**
@@ -29,7 +28,7 @@ import org.apache.sshd.common.util.buffer.Buffer;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public interface Compression extends NamedResource {
+public interface Compression extends CompressionInformation {
 
     /**
      * Enum identifying if this object will be used to compress
@@ -41,15 +40,6 @@ public interface Compression extends NamedResource {
     }
 
     /**
-     * Delayed compression is an Open-SSH specific feature which
-     * informs both the client and server to not compress data before
-     * the session has been authenticated.
-     *
-     * @return if the compression is delayed after authentication or not
-     */
-    boolean isDelayed();
-
-    /**
      * Initialize this object to either compress or uncompress data.
      * This method must be called prior to any calls to either
      * <code>compress</code> or <code>uncompress</code>.

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionFactory.java
index a6dd4c9..355594a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionFactory.java
@@ -25,7 +25,7 @@ import org.apache.sshd.common.BuiltinFactory;
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 // CHECKSTYLE:OFF
-public interface CompressionFactory extends BuiltinFactory<Compression> {
+public interface CompressionFactory extends BuiltinFactory<Compression>, CompressionInformation {
     // nothing extra
 }
 //CHECKSTYLE:ON

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionInformation.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionInformation.java b/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionInformation.java
new file mode 100644
index 0000000..428689f
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionInformation.java
@@ -0,0 +1,42 @@
+/*
+ * 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.compression;
+
+import org.apache.sshd.common.NamedResource;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface CompressionInformation extends NamedResource {
+    /**
+     * Delayed compression is an Open-SSH specific feature which
+     * informs both the client and server to not compress data before
+     * the session has been authenticated.
+     *
+     * @return if the compression is delayed after authentication or not
+     */
+    boolean isDelayed();
+
+    /**
+     * @return {@code true} if there is any compression executed by
+     * this &quot;compressor&quot; - special case for 'none'
+     */
+    boolean isCompressionExecuted();
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionNone.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionNone.java b/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionNone.java
new file mode 100644
index 0000000..815e8ce
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/compression/CompressionNone.java
@@ -0,0 +1,76 @@
+/*
+ * 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.compression;
+
+import java.io.IOException;
+import java.io.StreamCorruptedException;
+
+import org.apache.sshd.common.util.buffer.Buffer;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class CompressionNone extends BaseCompression {
+    private Type type;
+    private int level;
+
+    public CompressionNone() {
+        super(BuiltinCompressions.Constants.NONE);
+    }
+
+    @Override
+    public void init(Type type, int level) {
+        this.type = type;
+        this.level = level;
+    }
+
+    @Override
+    public boolean isCompressionExecuted() {
+        return false;
+    }
+
+    @Override
+    public void compress(Buffer buffer) throws IOException {
+        if (!Type.Deflater.equals(type)) {
+            throw new StreamCorruptedException("Not set up for compression: " + type);
+        }
+    }
+
+    @Override
+    public void uncompress(Buffer from, Buffer to) throws IOException {
+        if (!Type.Inflater.equals(type)) {
+            throw new StreamCorruptedException("Not set up for de-compression: " + type);
+        }
+
+        if (from != to) {
+            throw new StreamCorruptedException("Separate de-compression buffers provided");
+        }
+    }
+
+    @Override
+    public boolean isDelayed() {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "[" + type + "/" + level + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/main/java/org/apache/sshd/common/config/CompressionConfigValue.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/CompressionConfigValue.java b/sshd-core/src/main/java/org/apache/sshd/common/config/CompressionConfigValue.java
index c3bbe74..e153adc 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/CompressionConfigValue.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/CompressionConfigValue.java
@@ -68,6 +68,16 @@ public enum CompressionConfigValue implements CompressionFactory {
         return getName();
     }
 
+    @Override
+    public boolean isDelayed() {
+        return factory.isDelayed();
+    }
+
+    @Override
+    public boolean isCompressionExecuted() {
+        return factory.isCompressionExecuted();
+    }
+
     public static CompressionConfigValue fromName(String n) {
         if (GenericUtils.isEmpty(n)) {
             return null;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
index 02af7cf..1347245 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
@@ -47,7 +47,9 @@ import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.channel.ChannelListener;
 import org.apache.sshd.common.cipher.Cipher;
+import org.apache.sshd.common.cipher.CipherInformation;
 import org.apache.sshd.common.compression.Compression;
+import org.apache.sshd.common.compression.CompressionInformation;
 import org.apache.sshd.common.digest.Digest;
 import org.apache.sshd.common.future.DefaultKeyExchangeFuture;
 import org.apache.sshd.common.future.DefaultSshFuture;
@@ -60,6 +62,7 @@ import org.apache.sshd.common.kex.KexProposalOption;
 import org.apache.sshd.common.kex.KexState;
 import org.apache.sshd.common.kex.KeyExchange;
 import org.apache.sshd.common.mac.Mac;
+import org.apache.sshd.common.mac.MacInformation;
 import org.apache.sshd.common.random.Random;
 import org.apache.sshd.common.util.EventListenerUtils;
 import org.apache.sshd.common.util.GenericUtils;
@@ -319,6 +322,21 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
     }
 
     @Override
+    public CipherInformation getCipherInformation(boolean incoming) {
+        return incoming ? inCipher : outCipher;
+    }
+
+    @Override
+    public CompressionInformation getCompressionInformation(boolean incoming) {
+        return incoming ? inCompression : outCompression;
+    }
+
+    @Override
+    public MacInformation getMacInformation(boolean incoming) {
+        return incoming ? inMac : outMac;
+    }
+
+    @Override
     public boolean isAuthenticated() {
         return authed;
     }
@@ -844,10 +862,11 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
                 log.trace("encode({}) Sending packet #{}: {}", this, Long.valueOf(seqo), buffer.printHex());
             }
             // Compress the packet if needed
-            if ((outCompression != null) && (authed || !outCompression.isDelayed())) {
+            if ((outCompression != null) && outCompression.isCompressionExecuted() && (authed || (!outCompression.isDelayed()))) {
                 outCompression.compress(buffer);
                 len = buffer.available();
             }
+
             // Compute padding length
             int bsize = outCipherSize;
             int oldLen = len;
@@ -965,12 +984,13 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
                     Buffer buf;
                     int wpos = decoderBuffer.wpos();
                     // Decompress if needed
-                    if (inCompression != null && (authed || !inCompression.isDelayed())) {
+                    if ((inCompression != null) && inCompression.isCompressionExecuted() && (authed || (!inCompression.isDelayed()))) {
                         if (uncompressBuffer == null) {
                             uncompressBuffer = new ByteArrayBuffer();
                         } else {
                             uncompressBuffer.clear();
                         }
+
                         decoderBuffer.wpos(decoderBuffer.rpos() + decoderLength - 1 - pad);
                         inCompression.uncompress(decoderBuffer, uncompressBuffer);
                         buf = uncompressBuffer;
@@ -978,9 +998,11 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
                         decoderBuffer.wpos(decoderLength + 4 - pad);
                         buf = decoderBuffer;
                     }
+
                     if (log.isTraceEnabled()) {
                         log.trace("decode({}) Received packet #{}: {}", this, Long.valueOf(seqi), buf.printHex());
                     }
+
                     // Update stats
                     inPacketsCount.incrementAndGet();
                     inBytesCount.addAndGet(buf.available());
@@ -1267,12 +1289,18 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
         s2ccipher.init(isServer ? Cipher.Mode.Encrypt : Cipher.Mode.Decrypt, e_s2c, iv_s2c);
 
         value = getNegotiatedKexParameter(KexProposalOption.S2CMAC);
-        Mac s2cmac = ValidateUtils.checkNotNull(NamedFactory.Utils.create(getMacFactories(), value), "Unknown s2c mac: %s", value);
+        Mac s2cmac = NamedFactory.Utils.create(getMacFactories(), value);
+        if (s2cmac == null) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_MAC_ERROR, "Unknown s2c MAC: " + value);
+        }
         mac_s2c = resizeKey(mac_s2c, s2cmac.getBlockSize(), hash, k, h);
         s2cmac.init(mac_s2c);
 
         value = getNegotiatedKexParameter(KexProposalOption.S2CCOMP);
         Compression s2ccomp = NamedFactory.Utils.create(getCompressionFactories(), value);
+        if (s2ccomp == null) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_COMPRESSION_ERROR, "Unknown s2c compression: " + value);
+        }
 
         value = getNegotiatedKexParameter(KexProposalOption.C2SENC);
         Cipher c2scipher = ValidateUtils.checkNotNull(NamedFactory.Utils.create(getCipherFactories(), value), "Unknown c2s cipher: %s", value);
@@ -1280,12 +1308,18 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
         c2scipher.init(isServer ? Cipher.Mode.Decrypt : Cipher.Mode.Encrypt, e_c2s, iv_c2s);
 
         value = getNegotiatedKexParameter(KexProposalOption.C2SMAC);
-        Mac c2smac = ValidateUtils.checkNotNull(NamedFactory.Utils.create(getMacFactories(), value), "Unknown c2s mac: %s", value);
+        Mac c2smac = NamedFactory.Utils.create(getMacFactories(), value);
+        if (c2smac == null) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_MAC_ERROR, "Unknown c2s MAC: " + value);
+        }
         mac_c2s = resizeKey(mac_c2s, c2smac.getBlockSize(), hash, k, h);
         c2smac.init(mac_c2s);
 
         value = getNegotiatedKexParameter(KexProposalOption.C2SCOMP);
         Compression c2scomp = NamedFactory.Utils.create(getCompressionFactories(), value);
+        if (c2scomp == null) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_COMPRESSION_ERROR, "Unknown c2s compression: " + value);
+        }
 
         if (isServer) {
             outCipher = s2ccipher;
@@ -1303,14 +1337,11 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
             inCompression = s2ccomp;
         }
         outCipherSize = outCipher.getIVSize();
-        if (outCompression != null) {
-            outCompression.init(Compression.Type.Deflater, -1);
-        }
+        outCompression.init(Compression.Type.Deflater, -1);
+
         inCipherSize = inCipher.getIVSize();
         inMacResult = new byte[inMac.getBlockSize()];
-        if (inCompression != null) {
-            inCompression.init(Compression.Type.Inflater, -1);
-        }
+        inCompression.init(Compression.Type.Inflater, -1);
 
         // see https://tools.ietf.org/html/rfc4344#section-3.2
         int inBlockSize = inCipher.getBlockSize();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java b/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
index 0ac2705..db9de87 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
@@ -27,12 +27,15 @@ import org.apache.sshd.common.PropertyResolver;
 import org.apache.sshd.common.Service;
 import org.apache.sshd.common.auth.UsernameHolder;
 import org.apache.sshd.common.channel.ChannelListenerManager;
+import org.apache.sshd.common.cipher.CipherInformation;
+import org.apache.sshd.common.compression.CompressionInformation;
 import org.apache.sshd.common.future.KeyExchangeFuture;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.io.IoWriteFuture;
 import org.apache.sshd.common.kex.KexFactoryManager;
 import org.apache.sshd.common.kex.KexProposalOption;
 import org.apache.sshd.common.kex.KeyExchange;
+import org.apache.sshd.common.mac.MacInformation;
 import org.apache.sshd.common.util.buffer.Buffer;
 
 /**
@@ -116,6 +119,36 @@ public interface Session
     String getNegotiatedKexParameter(KexProposalOption paramType);
 
     /**
+     * Retrieves current cipher information - <B>Note:</B> may change if
+     * key re-exchange executed
+     *
+     * @param incoming If {@code true} then the cipher for the incoming data,
+     *                 otherwise for the outgoing data
+     * @return The {@link CipherInformation} - or {@code null} if not negotiated yet.
+     */
+    CipherInformation getCipherInformation(boolean incoming);
+
+    /**
+     * Retrieves current compression information - <B>Note:</B> may change if
+     * key re-exchange executed
+     *
+     * @param incoming If {@code true} then the compression for the incoming data,
+     *                 otherwise for the outgoing data
+     * @return The {@link CompressionInformation} - or {@code null} if not negotiated yet.
+     */
+    CompressionInformation getCompressionInformation(boolean incoming);
+
+    /**
+     * Retrieves current MAC information - <B>Note:</B> may change if
+     * key re-exchange executed
+     *
+     * @param incoming If {@code true} then the MAC for the incoming data,
+     *                 otherwise for the outgoing data
+     * @return The {@link MacInformation} - or {@code null} if not negotiated yet.
+     */
+    MacInformation getMacInformation(boolean incoming);
+
+    /**
      * Create a new buffer for the specified SSH packet and reserve the needed space
      * (5 bytes) for the packet header.
      *

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/test/java/org/apache/sshd/common/compression/BuiltinCompressionsTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/compression/BuiltinCompressionsTest.java b/sshd-core/src/test/java/org/apache/sshd/common/compression/BuiltinCompressionsTest.java
index c33353c..266cf93 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/compression/BuiltinCompressionsTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/compression/BuiltinCompressionsTest.java
@@ -165,5 +165,4 @@ public class BuiltinCompressionsTest extends BaseTestSupport {
             assertNull("Extension not un-registered", BuiltinCompressions.resolveFactory(name));
         }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/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 a5dfd53..e45c51c 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
@@ -33,6 +33,7 @@ import java.util.EnumSet;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
@@ -45,7 +46,6 @@ import org.apache.sshd.client.future.AuthFuture;
 import org.apache.sshd.client.session.ClientConnectionServiceFactory;
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.client.session.ClientSessionImpl;
-import org.apache.sshd.client.session.SessionFactory;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.PropertyResolverUtils;
@@ -63,6 +63,7 @@ import org.apache.sshd.common.util.OsUtils;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.deprecated.ClientUserAuthServiceOld;
 import org.apache.sshd.server.command.ScpCommandFactory;
+import org.apache.sshd.server.session.ServerSessionImpl;
 import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.EchoShell;
@@ -84,7 +85,6 @@ import org.slf4j.LoggerFactory;
 public class ServerTest extends BaseTestSupport {
     private SshServer sshd;
     private SshClient client;
-    private int port;
 
     public ServerTest() {
         super();
@@ -94,9 +94,6 @@ public class ServerTest extends BaseTestSupport {
     public void setUp() throws Exception {
         sshd = setupTestServer();
         sshd.setShellFactory(new TestEchoShellFactory());
-        sshd.start();
-        port = sshd.getPort();
-
         client = setupTestClient();
     }
 
@@ -120,13 +117,14 @@ public class ServerTest extends BaseTestSupport {
         final int MAX_AUTH_REQUESTS = 10;
         PropertyResolverUtils.updateProperty(sshd, ServerAuthenticationManager.MAX_AUTH_REQUESTS, MAX_AUTH_REQUESTS);
 
+        sshd.start();
         client.setServiceFactories(Arrays.asList(
                 new ClientUserAuthServiceOld.Factory(),
                 ClientConnectionServiceFactory.INSTANCE
         ));
         client.start();
 
-        try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+        try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, sshd.getPort()).verify(7L, TimeUnit.SECONDS).getSession()) {
             int nbTrials = 0;
             Collection<ClientSession.ClientSessionEvent> res = Collections.emptySet();
             Collection<ClientSession.ClientSessionEvent> mask =
@@ -149,12 +147,14 @@ public class ServerTest extends BaseTestSupport {
         final int MAX_AUTH_REQUESTS = 10;
         PropertyResolverUtils.updateProperty(sshd, ServerAuthenticationManager.MAX_AUTH_REQUESTS, MAX_AUTH_REQUESTS);
 
+        sshd.start();
+
         client.setServiceFactories(Arrays.asList(
                 new ClientUserAuthServiceOld.Factory(),
                 ClientConnectionServiceFactory.INSTANCE
         ));
         client.start();
-        try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+        try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, sshd.getPort()).verify(7L, TimeUnit.SECONDS).getSession()) {
             int nbTrials = 0;
             AuthFuture authFuture;
             do {
@@ -179,8 +179,9 @@ public class ServerTest extends BaseTestSupport {
         final long AUTH_TIMEOUT = TimeUnit.SECONDS.toMillis(5L);
         PropertyResolverUtils.updateProperty(sshd, FactoryManager.AUTH_TIMEOUT, AUTH_TIMEOUT);
 
+        sshd.start();
         client.start();
-        try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+        try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, sshd.getPort()).verify(7L, TimeUnit.SECONDS).getSession()) {
             Collection<ClientSession.ClientSessionEvent> res = s.waitFor(EnumSet.of(ClientSession.ClientSessionEvent.CLOSED), 2L * AUTH_TIMEOUT);
             assertTrue("Session should be closed: " + res,
                        res.containsAll(EnumSet.of(ClientSession.ClientSessionEvent.CLOSED, ClientSession.ClientSessionEvent.WAIT_AUTH)));
@@ -216,9 +217,10 @@ public class ServerTest extends BaseTestSupport {
 
         TestChannelListener channelListener = new TestChannelListener();
         sshd.addChannelListener(channelListener);
+        sshd.start();
 
         client.start();
-        try (ClientSession s = createTestClientSession();
+        try (ClientSession s = createTestClientSession(sshd);
              ChannelShell shell = s.createShellChannel();
              ByteArrayOutputStream out = new ByteArrayOutputStream();
              ByteArrayOutputStream err = new ByteArrayOutputStream()) {
@@ -282,10 +284,10 @@ public class ServerTest extends BaseTestSupport {
 
         TestChannelListener channelListener = new TestChannelListener();
         sshd.addChannelListener(channelListener);
+        sshd.start();
 
         client.start();
-
-        try (ClientSession s = createTestClientSession();
+        try (ClientSession s = createTestClientSession(sshd);
              ChannelExec shell = s.createExecChannel("normal");
              // Create a pipe that will block reading when the buffer is full
              PipedInputStream pis = new PipedInputStream();
@@ -328,11 +330,12 @@ public class ServerTest extends BaseTestSupport {
 
     @Test
     public void testLanguageNegotiation() throws Exception {
-        client.setSessionFactory(new SessionFactory(client) {
+        sshd.start();
+
+        client.setSessionFactory(new org.apache.sshd.client.session.SessionFactory(client) {
             @Override
-            @SuppressWarnings("synthetic-access")
-            protected ClientSessionImpl createSession(IoSession ioSession) throws Exception {
-                return new ClientSessionImpl(client, ioSession) {
+            protected ClientSessionImpl doCreateSession(IoSession ioSession) throws Exception {
+                return new ClientSessionImpl(getClient(), ioSession) {
                     @Override
                     protected Map<KexProposalOption, String> createProposal(String hostKeyTypes) {
                         Map<KexProposalOption, String> proposal = super.createProposal(hostKeyTypes);
@@ -344,9 +347,98 @@ public class ServerTest extends BaseTestSupport {
             }
         });
 
+        final Semaphore sigSem = new Semaphore(0, true);
+        client.addSessionListener(new SessionListener() {
+            @Override
+            public void sessionCreated(Session session) {
+                outputDebugMessage("Session created: %s", session);
+            }
+
+            @Override
+            public void sessionEvent(Session session, Event event) {
+                if (Event.KeyEstablished.equals(event)) {
+                    for (KexProposalOption option : new KexProposalOption[]{ KexProposalOption.S2CLANG, KexProposalOption.C2SLANG}) {
+                        assertNull("Unexpected negotiated language for " + option, session.getNegotiatedKexParameter(option));
+                    }
+
+                    sigSem.release();
+                }
+            }
+
+            @Override
+            public void sessionClosed(Session session) {
+                outputDebugMessage("Session closed: %s", session);
+            }
+        });
+
         client.start();
-        try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
-            // do nothing
+        try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, sshd.getPort()).verify(7L, TimeUnit.SECONDS).getSession()) {
+            assertTrue("Failed to receive signal on time", sigSem.tryAcquire(11L, TimeUnit.SECONDS));
+        } finally {
+            client.stop();
+        }
+    }
+
+    @Test   // see SSHD-609
+    public void testCompressionNegotiation() throws Exception {
+        sshd.setSessionFactory(new org.apache.sshd.server.session.SessionFactory(sshd) {
+            @Override
+            protected ServerSessionImpl doCreateSession(IoSession ioSession) throws Exception {
+                return new ServerSessionImpl(getServer(), ioSession) {
+                    @Override
+                    protected Map<KexProposalOption, String> createProposal(String hostKeyTypes) {
+                        Map<KexProposalOption, String> proposal = super.createProposal(hostKeyTypes);
+                        proposal.put(KexProposalOption.C2SCOMP, getCurrentTestName());
+                        proposal.put(KexProposalOption.S2CCOMP, getCurrentTestName());
+                        return proposal;
+                    }
+                };
+            }
+        });
+        sshd.start();
+
+        client.setSessionFactory(new org.apache.sshd.client.session.SessionFactory(client) {
+            @Override
+            protected ClientSessionImpl doCreateSession(IoSession ioSession) throws Exception {
+                return new ClientSessionImpl(getClient(), ioSession) {
+                    @Override
+                    protected Map<KexProposalOption, String> createProposal(String hostKeyTypes) {
+                        Map<KexProposalOption, String> proposal = super.createProposal(hostKeyTypes);
+                        proposal.put(KexProposalOption.C2SCOMP, getCurrentTestName());
+                        proposal.put(KexProposalOption.S2CCOMP, getCurrentTestName());
+                        return proposal;
+                    }
+                };
+            }
+        });
+
+        final Semaphore sigSem = new Semaphore(0, true);
+        client.addSessionListener(new SessionListener() {
+            @Override
+            public void sessionCreated(Session session) {
+                outputDebugMessage("Session created: %s", session);
+            }
+
+            @Override
+            public void sessionEvent(Session session, Event event) {
+                assertNotEquals("Unexpected key establishment success", Event.KeyEstablished, event);
+            }
+
+            @Override
+            public void sessionClosed(Session session) {
+                sigSem.release();
+            }
+        });
+
+        client.start();
+        try {
+            try (ClientSession s = client.connect(getCurrentTestName(), TEST_LOCALHOST, sshd.getPort()).verify(7L, TimeUnit.SECONDS).getSession()) {
+                assertTrue("Session closing not signalled on time", sigSem.tryAcquire(5L, TimeUnit.SECONDS));
+                for (boolean incoming : new boolean[]{true, false}) {
+                    assertNull("Unexpected compression information for incoming=" + incoming, s.getCompressionInformation(incoming));
+                }
+                assertFalse("Session unexpectedly still open", s.isOpen());
+            }
         } finally {
             client.stop();
         }
@@ -373,8 +465,8 @@ public class ServerTest extends BaseTestSupport {
                 // ignored
             }
         });
+        sshd.start();
 
-        client.start();
         final AtomicInteger clientEventCount = new AtomicInteger(0);
         client.addSessionListener(new SessionListener() {
             @Override
@@ -394,8 +486,9 @@ public class ServerTest extends BaseTestSupport {
                 // ignored
             }
         });
+        client.start();
 
-        try (ClientSession s = createTestClientSession()) {
+        try (ClientSession s = createTestClientSession(sshd)) {
             assertEquals("Mismatched client events count", 1, clientEventCount.get());
             assertEquals("Mismatched server events count", 1, serverEventCount.get());
             s.close(false);
@@ -454,6 +547,7 @@ public class ServerTest extends BaseTestSupport {
 
         TestChannelListener channelListener = new TestChannelListener();
         sshd.addChannelListener(channelListener);
+        sshd.start();
 
         @SuppressWarnings("synthetic-access")
         Map<String, String> expected = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER) {
@@ -461,13 +555,13 @@ public class ServerTest extends BaseTestSupport {
 
             {
                 put("test", getCurrentTestName());
-                put("port", Integer.toString(port));
+                put("port", Integer.toString(sshd.getPort()));
                 put("user", OsUtils.getCurrentUser());
             }
         };
 
         client.start();
-        try (ClientSession s = createTestClientSession();
+        try (ClientSession s = createTestClientSession(sshd);
              ChannelExec shell = s.createExecChannel(getCurrentTestName())) {
             for (Map.Entry<String, String> ee : expected.entrySet()) {
                 shell.setEnv(ee.getKey(), ee.getValue());
@@ -505,8 +599,8 @@ public class ServerTest extends BaseTestSupport {
         }
     }
 
-    private ClientSession createTestClientSession() throws Exception {
-        ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession();
+    private ClientSession createTestClientSession(SshServer server) throws Exception {
+        ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, server.getPort()).verify(7L, TimeUnit.SECONDS).getSession();
         try {
             session.addPasswordIdentity(getCurrentTestName());
             session.auth().verify(5L, TimeUnit.SECONDS);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/53055cb5/sshd-core/src/test/java/org/apache/sshd/server/SshServerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/SshServerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/SshServerTest.java
index 09b9ddc..a683afb 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/SshServerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/SshServerTest.java
@@ -32,6 +32,9 @@ import org.junit.runners.MethodSorters;
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class SshServerTest extends BaseTestSupport {
+    public SshServerTest() {
+        super();
+    }
 
     @Test
     public void stopMethodShouldBeIdempotent() throws Exception {