PROTON-1962: update some defaults and related handling
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java
index 279d934..06a3517 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java
@@ -49,15 +49,24 @@
     /**
      * Determines the level of peer validation.
      *
-     * {@link #ANONYMOUS_PEER} is configured by default.
+     * {@link #VERIFY_PEER_NAME} is used by default in {@link Mode#CLIENT client}
+     * mode if not configured otherwise, with {@link #ANONYMOUS_PEER} used for
+     * {@link Mode#SERVER server} mode if not configured otherwise.
      */
     public enum VerifyMode
     {
         /**
-         * will only connect to those peers that provide a valid identifying certificate signed
-         * by a trusted CA and are using an authenticated cipher
+         * Requires peers provide a valid identifying certificate signed by
+         * a trusted certificate. Does not verify hostname details of the
+         * peer certificate, use {@link #VERIFY_PEER_NAME} for this instead.
          */
         VERIFY_PEER,
+        /**
+         * Requires peers provide a valid identifying certificate signed
+         * by a trusted certificate, including verifying hostname details
+         * of the certificate using peer details provided when configuring
+         * TLS via {@link Transport#ssl(SslDomain, SslPeerDetails)}.
+         */
         VERIFY_PEER_NAME,
         /**
          * does not require a valid certificate, and permits use of ciphers that
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/Transport.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/Transport.java
index f8de042..66cde84 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/Transport.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/Transport.java
@@ -194,15 +194,21 @@
      * {@link Ssl} object, regardless of the parameters supplied.
      *
      * @param sslDomain the SSL settings to use
-     * @param sslPeerDetails may be null, in which case SSL session resume will not be attempted
+     * @param sslPeerDetails peer details, used for SNI, hostname verification, etc when connecting. May be null.
      * @return an {@link Ssl} object representing the SSL session.
+     * @throws IllegalArgumentException if the sslDomain requests hostname verification but sslPeerDetails are null.
+     * @throws IllegalStateException if the sslDomain has not been initialised.
      */
-    Ssl ssl(SslDomain sslDomain, SslPeerDetails sslPeerDetails);
+    Ssl ssl(SslDomain sslDomain, SslPeerDetails sslPeerDetails) throws IllegalArgumentException;
 
     /**
-     * As per {@link #ssl(SslDomain, SslPeerDetails)} but no attempt is made to resume a previous SSL session.
+     * Equivalent to {@link #ssl(SslDomain, SslPeerDetails)} but passing null for SslPeerDetails, meaning no SNI detail
+     * is sent, hostname verification isn't supported etc when connecting.
+     *
+     * @throws IllegalArgumentException if the sslDomain requests hostname verification.
+     * @throws IllegalStateException if the sslDomain has not been initialised.
      */
-    Ssl ssl(SslDomain sslDomain);
+    Ssl ssl(SslDomain sslDomain) throws IllegalArgumentException;
 
 
     /**
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapper.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapper.java
index a30e88b..f2454b3 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapper.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapper.java
@@ -360,9 +360,15 @@
         try {
             unwrapInput();
         } catch (SSLException e) {
-            _logger.log(Level.WARNING, e.getMessage());
+            if(_logger.isLoggable(Level.FINEST)){
+                _logger.log(Level.FINEST, e.getMessage(), e);
+            } else {
+                _logger.log(Level.WARNING, e.getMessage());
+            }
             _inputBuffer.position(_inputBuffer.limit());
             _tail_closed = true;
+
+            throw new TransportException(e);
         } finally {
             _inputBuffer.compact();
         }
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java
index 3928b05..fddde1a 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java
@@ -19,7 +19,6 @@
 package org.apache.qpid.proton.engine.impl.ssl;
 
 import javax.net.ssl.SSLContext;
-import org.apache.qpid.proton.ProtonUnsupportedOperationException;
 import org.apache.qpid.proton.engine.ProtonJSslDomain;
 import org.apache.qpid.proton.engine.SslDomain;
 import org.apache.qpid.proton.engine.SslPeerDetails;
@@ -27,7 +26,7 @@
 public class SslDomainImpl implements SslDomain, ProtonSslEngineProvider, ProtonJSslDomain
 {
     private Mode _mode;
-    private VerifyMode _verifyMode = VerifyMode.ANONYMOUS_PEER;
+    private VerifyMode _verifyMode;
     private String _certificateFile;
     private String _privateKeyFile;
     private String _privateKeyPassword;
@@ -94,10 +93,6 @@
     @Override
     public void setPeerAuthentication(VerifyMode verifyMode)
     {
-        if(verifyMode == VerifyMode.VERIFY_PEER_NAME)
-        {
-            throw new ProtonUnsupportedOperationException();
-        }
         _verifyMode = verifyMode;
         _sslEngineFacadeFactory.resetCache();
     }
@@ -105,6 +100,11 @@
     @Override
     public VerifyMode getPeerAuthentication()
     {
+        if(_verifyMode == null)
+        {
+           return _mode == Mode.SERVER ? VerifyMode.ANONYMOUS_PEER : VerifyMode.VERIFY_PEER_NAME;
+        }
+
         return _verifyMode;
     }
 
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java
index 309e0dc..6a730df 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java
@@ -53,6 +53,7 @@
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
@@ -232,6 +233,13 @@
             {
                 sslEngine.setNeedClientAuth(true);
             }
+
+            if(domain.getPeerAuthentication() == SslDomain.VerifyMode.VERIFY_PEER_NAME)
+            {
+                SSLParameters sslParameters = sslEngine.getSSLParameters();
+                sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
+                sslEngine.setSSLParameters(sslParameters);
+            }
         }
 
         if(_logger.isLoggable(Level.FINE))
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslImpl.java
index de99351..24d7c43 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslImpl.java
@@ -25,6 +25,7 @@
 import org.apache.qpid.proton.ProtonUnsupportedOperationException;
 import org.apache.qpid.proton.engine.Ssl;
 import org.apache.qpid.proton.engine.SslDomain;
+import org.apache.qpid.proton.engine.SslDomain.VerifyMode;
 import org.apache.qpid.proton.engine.SslPeerDetails;
 import org.apache.qpid.proton.engine.Transport;
 import org.apache.qpid.proton.engine.TransportException;
@@ -54,6 +55,14 @@
         _domain = domain;
         _protonSslEngineProvider = (ProtonSslEngineProvider)domain;
         _peerDetails = peerDetails;
+
+        if(_domain.getMode() == null) {
+            throw new IllegalStateException("Client/server mode must be configured, SslDomain must have init called.");
+        }
+
+        if(_peerDetails == null && _domain.getPeerAuthentication() == VerifyMode.VERIFY_PEER_NAME) {
+            throw new IllegalArgumentException("Peer hostname verification is enabled, but no peer details were provided");
+        }
     }
 
     public TransportWrapper wrap(TransportInput inputProcessor, TransportOutput outputProcessor)
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java b/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java
index 81b85ff..5d58182 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java
@@ -37,6 +37,7 @@
 import org.apache.qpid.proton.engine.Event;
 import org.apache.qpid.proton.engine.Sasl;
 import org.apache.qpid.proton.engine.Transport;
+import org.apache.qpid.proton.engine.TransportException;
 import org.apache.qpid.proton.engine.impl.TransportImpl;
 import org.apache.qpid.proton.engine.Record;
 import org.apache.qpid.proton.reactor.Reactor;
@@ -232,7 +233,7 @@
                     } else {
                         transport.process();
                     }
-                } catch (IOException e) {
+                } catch (IOException | TransportException e) {
                     ErrorCondition condition = new ErrorCondition();
                     condition.setCondition(Symbol.getSymbol("proton:io"));
                     condition.setDescription(e.getMessage());
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapperTest.java b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapperTest.java
index 6ee1582..605046c 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapperTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapperTest.java
@@ -347,12 +347,19 @@
     @Test
     public void testSslUnwrapThrowsException_returnsErrorResultAndRefusesFurtherInput() throws Exception
     {
-        SSLException sslException = new SSLException("unwrap exception");
+        String unwrapExceptionMessage = "unwrap exception message";
+        SSLException sslException = new SSLException(unwrapExceptionMessage);
         _dummySslEngine.rejectNextEncodedPacket(sslException);
 
         _sslWrapper.tail().put("<-A->".getBytes(StandardCharsets.UTF_8));
-        _sslWrapper.process();
-        assertEquals(_sslWrapper.capacity(), Transport.END_OF_STREAM);
+        try {
+            _sslWrapper.process();
+            fail("no exception");
+        } catch(TransportException e) {
+            assertEquals("javax.net.ssl.SSLException: " + unwrapExceptionMessage, e.getMessage());
+        }
+
+        assertEquals(Transport.END_OF_STREAM, _sslWrapper.capacity());
     }
 
     @Test
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImplTest.java b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImplTest.java
new file mode 100644
index 0000000..e0d7a5d
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImplTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.qpid.proton.engine.impl.ssl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+
+import org.apache.qpid.proton.engine.SslDomain;
+import org.apache.qpid.proton.engine.SslDomain.Mode;
+import org.apache.qpid.proton.engine.SslDomain.VerifyMode;
+import org.junit.Test;
+
+public class SslDomainImplTest {
+
+    @Test
+    public void testInitGetMode() throws Exception
+    {
+        SslDomain sslDomain = SslDomain.Factory.create();
+        assertNull("Unexpected mode, none was set", sslDomain.getMode());
+
+        sslDomain.init(Mode.CLIENT);
+        assertEquals("Unexpected mode", Mode.CLIENT, sslDomain.getMode());
+
+        sslDomain.init(Mode.SERVER);
+        assertEquals("Unexpected mode", Mode.SERVER, sslDomain.getMode());
+    }
+
+    @Test
+    public void testVerifyModeDefault() throws Exception
+    {
+        SslDomain clientSslDomain = SslDomain.Factory.create();
+        assertEquals("Unexpected default verification mode", VerifyMode.VERIFY_PEER_NAME, clientSslDomain.getPeerAuthentication());
+        clientSslDomain.init(Mode.CLIENT);
+        assertEquals("Unexpected default verification mode", VerifyMode.VERIFY_PEER_NAME, clientSslDomain.getPeerAuthentication());
+
+        SslDomain serverSslDomain = SslDomain.Factory.create();
+        serverSslDomain.init(Mode.SERVER);
+        assertEquals("Unexpected default verification mode", VerifyMode.ANONYMOUS_PEER, serverSslDomain.getPeerAuthentication());
+    }
+
+    @Test
+    public void testVerifyModeSetGet() throws Exception
+    {
+        SslDomain clientSslDomain = SslDomain.Factory.create();
+        clientSslDomain.init(Mode.CLIENT);
+        assertNotEquals("Unexpected verification mode", VerifyMode.VERIFY_PEER, clientSslDomain.getPeerAuthentication());
+        clientSslDomain.setPeerAuthentication(VerifyMode.VERIFY_PEER);
+        assertEquals("Unexpected verification mode", VerifyMode.VERIFY_PEER, clientSslDomain.getPeerAuthentication());
+
+        SslDomain serverSslDomain = SslDomain.Factory.create();
+        serverSslDomain.init(Mode.SERVER);
+        assertNotEquals("Unexpected verification mode", VerifyMode.VERIFY_PEER, serverSslDomain.getPeerAuthentication());
+        serverSslDomain.setPeerAuthentication(VerifyMode.VERIFY_PEER);
+        assertEquals("Unexpected verification mode", VerifyMode.VERIFY_PEER, serverSslDomain.getPeerAuthentication());
+    }
+}
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/SslTest.java b/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/SslTest.java
index 32ab62d..962bd2b 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/SslTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/SslTest.java
@@ -22,6 +22,8 @@
 import static org.apache.qpid.proton.engine.EndpointState.UNINITIALIZED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -31,6 +33,8 @@
 
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
 import javax.net.ssl.TrustManagerFactory;
 
 import org.apache.qpid.proton.Proton;
@@ -41,7 +45,9 @@
 import org.apache.qpid.proton.engine.SslDomain;
 import org.apache.qpid.proton.engine.SslDomain.Mode;
 import org.apache.qpid.proton.engine.SslDomain.VerifyMode;
+import org.apache.qpid.proton.engine.SslPeerDetails;
 import org.apache.qpid.proton.engine.Transport;
+import org.apache.qpid.proton.engine.TransportException;
 import org.junit.Test;
 
 public class SslTest
@@ -67,6 +73,27 @@
     private final Connection _serverConnection = Proton.connection();
 
     @Test
+    public void testFailureToInitSslDomainThrowsISE() throws Exception {
+        SslDomain sslDomain = SslDomain.Factory.create();
+
+        try {
+            _clientTransport.ssl(sslDomain, null);
+            fail("Expected an exception to be thrown");
+        } catch (IllegalStateException ise) {
+            // Expected
+            assertTrue(ise.getMessage().contains("Client/server mode must be configured"));
+        }
+
+        try {
+            _serverTransport.ssl(sslDomain);
+            fail("Expected an exception to be thrown");
+        } catch (IllegalStateException ise) {
+            // Expected
+            assertTrue(ise.getMessage().contains("Client/server mode must be configured"));
+        }
+    }
+
+    @Test
     public void testOpenConnectionsWithProvidedSslContext() throws Exception
     {
         SslDomain clientSslDomain = SslDomain.Factory.create();
@@ -125,6 +152,143 @@
         assertConditions(_serverTransport);
     }
 
+    @Test
+    public void testHostnameVerificationSuccess() throws Exception {
+        doHostnameVerificationTestImpl(true, true);
+    }
+
+    @Test
+    public void testHostnameVerificationFailure() throws Exception {
+        doHostnameVerificationTestImpl(false, true);
+    }
+
+    @Test
+    public void testHostnameVerificationSkipped() throws Exception {
+        doHostnameVerificationTestImpl(false, false);
+    }
+
+    private void doHostnameVerificationTestImpl(boolean useMatchingServerName, boolean useHostnameVerification) throws Exception {
+        final String serverPeerName = useMatchingServerName ? "localhost" : "anotherserverhost";
+        final VerifyMode clientVerifyMode = useHostnameVerification ? VerifyMode.VERIFY_PEER_NAME : VerifyMode.VERIFY_PEER;
+
+        SslDomain clientSslDomain = SslDomain.Factory.create();
+        clientSslDomain.init(Mode.CLIENT);
+        clientSslDomain.setPeerAuthentication(clientVerifyMode);
+
+        SSLContext clientSslContext = createSslContext(CLIENT_JKS_KEYSTORE, PASSWORD, CLIENT_JKS_TRUSTSTORE, PASSWORD);
+        clientSslDomain.setSslContext(clientSslContext);
+        SslPeerDetails sslPeerDetails = SslPeerDetails.Factory.create(serverPeerName, 1234);
+        _clientTransport.ssl(clientSslDomain, sslPeerDetails);
+
+        SslDomain serverSslDomain = SslDomain.Factory.create();
+        serverSslDomain.init(Mode.SERVER);
+        serverSslDomain.setPeerAuthentication(VerifyMode.VERIFY_PEER_NAME);
+        SSLContext serverSslContext = createSslContext(SERVER_JKS_KEYSTORE, PASSWORD, SERVER_JKS_TRUSTSTORE, PASSWORD);
+        serverSslDomain.setSslContext(serverSslContext);
+        _serverTransport.ssl(serverSslDomain, SslPeerDetails.Factory.create("client", 4567));
+
+        _clientConnection.setContainer(CLIENT_CONTAINER);
+        _serverConnection.setContainer(SERVER_CONTAINER);
+
+        _clientTransport.bind(_clientConnection);
+        _serverTransport.bind(_serverConnection);
+
+        assertConditions(_clientTransport);
+        assertConditions(_serverTransport);
+
+        _clientConnection.open();
+
+        assertEndpointState(_clientConnection, ACTIVE, UNINITIALIZED);
+        assertEndpointState(_serverConnection, UNINITIALIZED, UNINITIALIZED);
+
+        assertConditions(_clientTransport);
+        assertConditions(_serverTransport);
+
+        if(useHostnameVerification && !useMatchingServerName) {
+            // Verify the expected failures and resulting transport closures
+            pumpWithFailingNegotiation();
+
+            assertEquals(Transport.END_OF_STREAM, _clientTransport.pending());
+            assertEquals(Transport.END_OF_STREAM, _clientTransport.capacity());
+
+            assertEquals(Transport.END_OF_STREAM, _serverTransport.pending());
+            assertEquals(Transport.END_OF_STREAM, _serverTransport.capacity());
+            return;
+        } else {
+            // Verify the connections succeed
+            _pumper.pumpAll();
+
+            assertEndpointState(_clientConnection, ACTIVE, UNINITIALIZED);
+            assertEndpointState(_serverConnection, UNINITIALIZED, ACTIVE);
+
+            assertConditions(_clientTransport);
+            assertConditions(_serverTransport);
+
+            _serverConnection.open();
+
+            assertEndpointState(_clientConnection, ACTIVE, UNINITIALIZED);
+            assertEndpointState(_serverConnection, ACTIVE, ACTIVE);
+
+            assertConditions(_clientTransport);
+            assertConditions(_serverTransport);
+
+            _pumper.pumpAll();
+
+            assertEndpointState(_clientConnection, ACTIVE, ACTIVE);
+            assertEndpointState(_serverConnection, ACTIVE, ACTIVE);
+
+            assertConditions(_clientTransport);
+            assertConditions(_serverTransport);
+        }
+    }
+
+    @Test
+    public void testOmittingPeerDetailsThrowsIAEWhenRequired() throws Exception {
+        doOmitPeerDetailsThrowsIAEWhenRequiredTestImpl(true);
+        doOmitPeerDetailsThrowsIAEWhenRequiredTestImpl(false);
+    }
+
+    private void doOmitPeerDetailsThrowsIAEWhenRequiredTestImpl(boolean explicitlySetVerifyMode) {
+        SslDomain clientSslDomain = SslDomain.Factory.create();
+        clientSslDomain.init(Mode.CLIENT);
+
+        if (explicitlySetVerifyMode) {
+            clientSslDomain.setPeerAuthentication(VerifyMode.VERIFY_PEER_NAME);
+        }
+
+        try {
+            _clientTransport.ssl(clientSslDomain, null);
+            fail("Expected an exception to be thrown");
+        } catch (IllegalArgumentException ise) {
+            // Expected
+        }
+
+        try {
+            _clientTransport.ssl(clientSslDomain);
+            fail("Expected an exception to be thrown");
+        } catch (IllegalArgumentException ise) {
+            // Expected
+        }
+    }
+
+    private void pumpWithFailingNegotiation() throws Exception {
+        try {
+            _pumper.pumpAll();
+            fail("Expected an exception");
+        } catch (TransportException te) {
+            assertTrue(te.getCause().getCause() instanceof SSLHandshakeException);
+        }
+
+        try {
+            _pumper.pumpAll();
+            fail("Expected an exception");
+        } catch (TransportException te) {
+            assertTrue(te.getCause().getCause() instanceof SSLException);
+        }
+
+        _pumper.pumpAll();
+    }
+
     private void assertConditions(Transport transport)
     {
         ErrorCondition remoteCondition = transport.getRemoteCondition();
diff --git a/tests/python/proton_tests/ssl.py b/tests/python/proton_tests/ssl.py
index 1a05780..518ef4d 100644
--- a/tests/python/proton_tests/ssl.py
+++ b/tests/python/proton_tests/ssl.py
@@ -25,6 +25,7 @@
 import subprocess
 import sys
 from proton import *
+from org.apache.qpid.proton.engine import TransportException
 from .common import Skipped, pump
 
 
@@ -82,6 +83,25 @@
     def _pump(self, ssl_client, ssl_server, buffer_size=1024):
         pump(ssl_client.transport, ssl_server.transport, buffer_size)
 
+    def _pump_with_failing_negotiation(self, client, server, onesided = False):
+        # Exception once for client/server transport
+        try:
+            self._pump( client, server )
+            assert False, "Expected exception did not occur!"
+        except TransportException:
+            pass
+
+        if(onesided != True):
+            # Exception once for server/client transport
+            try:
+                self._pump( client, server )
+                assert False, "Expected exception did not occur!"
+            except TransportException:
+                pass
+
+        # Ensure both are processed to completion
+        self._pump( client, server )
+
     def _do_handshake(self, client, server):
         """ Attempt to connect client to server. Will throw a TransportException if the SSL
         handshake fails.
@@ -154,6 +174,8 @@
                                            self._testpath("server-private-key.pem"),
                                            "server-password")
         server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+
+        self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
         client = SslTest.SslTestConnection( self.client_domain )
 
         client.connection.open()
@@ -235,7 +257,7 @@
 
         client.connection.open()
         server.connection.open()
-        self._pump( client, server )
+        self._pump_with_failing_negotiation(client, server)
         assert client.transport.closed
         assert server.transport.closed
         assert client.connection.state & Endpoint.REMOTE_UNINIT
@@ -260,7 +282,7 @@
 
         client.connection.open()
         server.connection.open()
-        self._pump( client, server )
+        self._pump_with_failing_negotiation(client, server)
         assert client.transport.closed
         assert server.transport.closed
         assert client.connection.state & Endpoint.REMOTE_UNINIT
@@ -335,7 +357,7 @@
 
         client.connection.open()
         server.connection.open()
-        self._pump( client, server )
+        self._pump_with_failing_negotiation(client, server)
         assert client.transport.closed
         assert server.transport.closed
         assert client.connection.state & Endpoint.REMOTE_UNINIT
@@ -430,7 +452,7 @@
 
         client.connection.open()
         server.connection.open()
-        self._pump( client, server )
+        self._pump_with_failing_negotiation(client, server, onesided = True)
         assert client.transport.closed
         assert server.transport.closed
         assert client.connection.state & Endpoint.REMOTE_UNINIT
@@ -479,6 +501,7 @@
     def test_singleton(self):
         """Verify that only a single instance of SSL can exist per Transport"""
         transport = Transport()
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
         ssl1 = SSL(transport, self.client_domain)
         ssl2 = transport.ssl(self.client_domain)
         ssl3 = transport.ssl(self.client_domain)