Repository: apache/qpid-dispatch

Issue:
DISPATCH-1797: Added a retry to qdmanage to make sure we give enough …
…time for addresses to be added to the router address table


Discussion:
# [Codecov](https://codecov.io/gh/apache/qpid-dispatch/pull/1255?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) Report
> Merging [#1255](https://codecov.io/gh/apache/qpid-dispatch/pull/1255?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (559f1ee) into [main](https://codecov.io/gh/apache/qpid-dispatch/commit/9e87b8994d29cfba97789a246e5df20c4ac29cab?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (9e87b89) will **increase** coverage by `0.06%`.
> The diff coverage is `n/a`.

> :exclamation: Current head 559f1ee differs from pull request most recent head 683bbaf. Consider uploading reports for the commit 683bbaf to get more accurate results
[![Impacted file tree graph](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/graphs/tree.svg?width=650&height=150&src=pr&token=rk2Cgd27pP&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)](https://codecov.io/gh/apache/qpid-dispatch/pull/1255?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)

```diff
@@            Coverage Diff             @@
##             main    #1255      +/-   ##
==========================================
+ Coverage   84.64%   84.70%   +0.06%     
==========================================
  Files         113      113              
  Lines       28043    28042       -1     
==========================================
+ Hits        23736    23752      +16     
+ Misses       4307     4290      -17     
```


| [Impacted Files](https://codecov.io/gh/apache/qpid-dispatch/pull/1255?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) | Coverage Δ | |
|---|---|---|
| [src/router\_core/route\_tables.c](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL3JvdXRlcl9jb3JlL3JvdXRlX3RhYmxlcy5j) | `82.70% <0.00%> (-0.58%)` | :arrow_down: |
| [src/router\_core/transfer.c](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL3JvdXRlcl9jb3JlL3RyYW5zZmVyLmM=) | `93.53% <0.00%> (-0.44%)` | :arrow_down: |
| [src/parse.c](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL3BhcnNlLmM=) | `87.96% <0.00%> (-0.22%)` | :arrow_down: |
| [src/router\_core/delivery.c](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL3JvdXRlcl9jb3JlL2RlbGl2ZXJ5LmM=) | `93.33% <0.00%> (-0.19%)` | :arrow_down: |
| [src/adaptors/http1/http1\_codec.c](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL2FkYXB0b3JzL2h0dHAxL2h0dHAxX2NvZGVjLmM=) | `85.03% <0.00%> (-0.13%)` | :arrow_down: |
| [src/message.c](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL21lc3NhZ2UuYw==) | `87.32% <0.00%> (-0.01%)` | :arrow_down: |
| [src/iterator.c](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL2l0ZXJhdG9yLmM=) | `89.48% <0.00%> (+0.18%)` | :arrow_up: |
| [src/adaptors/tcp\_adaptor.c](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL2FkYXB0b3JzL3RjcF9hZGFwdG9yLmM=) | `76.15% <0.00%> (+0.23%)` | :arrow_up: |
| [src/adaptors/http1/http1\_server.c](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL2FkYXB0b3JzL2h0dHAxL2h0dHAxX3NlcnZlci5j) | `84.86% <0.00%> (+0.29%)` | :arrow_up: |
| [src/router\_core/modules/edge\_router/edge\_mgmt.c](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL3JvdXRlcl9jb3JlL21vZHVsZXMvZWRnZV9yb3V0ZXIvZWRnZV9tZ210LmM=) | `85.14% <0.00%> (+0.99%)` | :arrow_up: |
| ... and [2 more](https://codecov.io/gh/apache/qpid-dispatch/pull/1255/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/apache/qpid-dispatch/pull/1255?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/apache/qpid-dispatch/pull/1255?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation). Last update [9e87b89...683bbaf](https://codecov.io/gh/apache/qpid-dispatch/pull/1255?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation).


Resolving patch:
diff --git a/python/qpid_dispatch_internal/tools/command.py b/python/qpid_dispatch_internal/tools/command.py
--- a/python/qpid_dispatch_internal/tools/command.py
+++ b/python/qpid_dispatch_internal/tools/command.py
@@ -261,9 +261,8 @@ def opts_url(opts):
     url = Url(opts.bus)
 
     # If the options indicate SSL, make sure we use the amqps scheme.
-    if opts.ssl_certificate or opts.ssl_trustfile:
+    if opts.ssl_certificate or opts.ssl_trustfile or opts.bus.startswith("amqps:"):
         url.scheme = "amqps"
-
     return url
 
 
@@ -282,6 +281,10 @@ def opts_ssl_domain(opts, mode=SSLDomain.MODE_CLIENT):
     @param opts: Parsed optoins including connection_options()
     """
 
+    url = opts_url(opts)
+    if not url.scheme == "amqps":
+        return None
+
     certificate, key, trustfile, password, password_file, ssl_disable_peer_name_verify = opts.ssl_certificate,\
         opts.ssl_key,\
         opts.ssl_trustfile,\
@@ -289,9 +292,6 @@ def opts_ssl_domain(opts, mode=SSLDomain.MODE_CLIENT):
         opts.ssl_password_file, \
         opts.ssl_disable_peer_name_verify
 
-    if not (certificate or trustfile):
-        return None
-
     if password_file:
         password = get_password(password_file)
 
@@ -299,10 +299,11 @@ def opts_ssl_domain(opts, mode=SSLDomain.MODE_CLIENT):
 
     if trustfile:
         domain.set_trusted_ca_db(str(trustfile))
-        if ssl_disable_peer_name_verify:
-            domain.set_peer_authentication(SSLDomain.VERIFY_PEER, str(trustfile))
-        else:
-            domain.set_peer_authentication(SSLDomain.VERIFY_PEER_NAME, str(trustfile))
+
+    if ssl_disable_peer_name_verify:
+        domain.set_peer_authentication(SSLDomain.VERIFY_PEER)
+    else:
+        domain.set_peer_authentication(SSLDomain.VERIFY_PEER_NAME)
 
     if certificate:
         domain.set_credentials(str(certificate), str(key), str(password))


Test patch:
diff --git a/tests/authservice.py.in b/tests/authservice.py.in
--- a/tests/authservice.py.in
+++ b/tests/authservice.py.in
@@ -18,18 +18,23 @@
 # under the License.
 #
 
+
 from __future__ import unicode_literals
 from __future__ import division
 from __future__ import absolute_import
 from __future__ import print_function
 
+
 import sys
 import signal
 import optparse
+import os
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
 from proton import Array, Data, symbol, UNDESCRIBED
+from proton import SSLDomain
 from cproton import pn_sasl_config_path
+import system_test
 
 
 class AuthService(MessagingHandler):
@@ -42,6 +47,15 @@ class AuthService(MessagingHandler):
         self.listener = None
         self.tmo = 0.1  # seconds
         self.stop_req = False
+        self.acceptor = None
+        self.ssl_domain = SSLDomain(SSLDomain.MODE_SERVER)
+        self.ssl_domain.set_credentials(self.ssl_file('server-certificate.pem'),
+                                        self.ssl_file('server-private-key.pem'),
+                                        password="server-password")
+        self.ssl_domain.set_trusted_ca_db(self.ssl_file('ca-certificate.pem'))
+
+    def ssl_file(self, name):
+        return os.path.join(system_test.DIR, 'ssl_certs', name)
 
     def allow(self, user, address, permissions):
         if not self.permissions.get(user):
@@ -49,7 +63,7 @@ class AuthService(MessagingHandler):
         self.permissions[user][address] = Array(UNDESCRIBED, Data.STRING, *permissions)
 
     def on_start(self, event):
-        self.listener = event.container.listen(self.address)
+        self.listener = event.container.listen(self.address, ssl_domain=self.ssl_domain)
         event.container.schedule(self.tmo, self)
 
     def stop(self):
diff --git a/tests/system_tests_authz_service_plugin.py.in b/tests/system_tests_authz_service_plugin.py.in
--- a/tests/system_tests_authz_service_plugin.py.in
+++ b/tests/system_tests_authz_service_plugin.py.in
@@ -57,6 +57,10 @@ sasldb_path: users.sasldb
 mech_list: SCRAM-SHA-1 PLAIN
 """)
 
+    @staticmethod
+    def ssl_file(name):
+        return os.path.join(DIR, 'ssl_certs', name)
+
     @classmethod
     def setUpClass(cls):
         """
@@ -71,18 +75,18 @@ mech_list: SCRAM-SHA-1 PLAIN
 
         cls.auth_service_port = cls.tester.get_port()
         cls.tester.popen(['/usr/bin/env', '${PY_STRING}', os.path.join(os.path.dirname(os.path.abspath(__file__)), 'authservice.py'),
-                          '-a', 'amqps://127.0.0.1:%d' % cls.auth_service_port, '-c', os.getcwd()], expect=Process.RUNNING)
+                          '-a', 'amqps://localhost:%d' % cls.auth_service_port, '-c', os.getcwd()], expect=Process.RUNNING)
 
         policy_config_path = os.path.join(DIR, 'policy-authz')
 
         cls.router_port = cls.tester.get_port()
         cls.tester.qdrouterd('router', Qdrouterd.Config([
-            ('sslProfile', {'name': 'myssl'}),
+            ('sslProfile', {'name': 'myssl', 'caCertFile': cls.ssl_file('ca-certificate.pem')}),
             ('policy', {'maxConnections': 2, 'policyDir': policy_config_path, 'enableVhostPolicy': 'true'}),
             # authService attribute has been deprecated. We are using it here to make sure that we are
             # still backward compatible.
-            ('authServicePlugin', {'name': 'myauth', 'sslProfile': 'myssl', 'port': cls.auth_service_port, 'host': '127.0.0.1'}),
-            ('listener', {'host': '0.0.0.0', 'port': cls.router_port, 'role': 'normal', 'saslPlugin': 'myauth', 'saslMechanisms': 'SCRAM-SHA-1 PLAIN'}),
+            ('authServicePlugin', {'name': 'myauth', 'sslProfile': 'myssl', 'port': cls.auth_service_port, 'host': 'localhost'}),
+            ('listener', {'host': 'localhost', 'port': cls.router_port, 'role': 'normal', 'saslPlugin': 'myauth', 'saslMechanisms': 'SCRAM-SHA-1 PLAIN'}),
             ('router', {'mode': 'standalone', 'id': 'router',
                         'saslConfigName': 'tests-mech-SCRAM',
                         'saslConfigPath': os.getcwd()})
@@ -156,15 +160,15 @@ class AuthServicePluginAuthzDeprecatedTest(AuthServicePluginAuthzTest):
 
         cls.auth_service_port = cls.tester.get_port()
         cls.tester.popen(['/usr/bin/env', '${PY_STRING}', os.path.join(os.path.dirname(os.path.abspath(__file__)), 'authservice.py'),
-                          '-a', 'amqps://127.0.0.1:%d' % cls.auth_service_port, '-c', os.getcwd()], expect=Process.RUNNING)
+                          '-a', 'amqps://localhost:%d' % cls.auth_service_port, '-c', os.getcwd()], expect=Process.RUNNING)
 
         cls.router_port = cls.tester.get_port()
         cls.tester.qdrouterd('router', Qdrouterd.Config([
-            ('sslProfile', {'name': 'myssl'}),
+            ('sslProfile', {'name': 'myssl', 'caCertFile': cls.ssl_file('ca-certificate.pem')}),
             # authService and authSslProfile attributea have been deprecated.
             # We are using it here to make sure that we are backward compatible.
-            ('authServicePlugin', {'name': 'myauth', 'authSslProfile': 'myssl', 'authService': '127.0.0.1:%d' % cls.auth_service_port}),
-            ('listener', {'host': '0.0.0.0', 'port': cls.router_port, 'role': 'normal', 'saslPlugin': 'myauth', 'saslMechanisms': 'SCRAM-SHA-1 PLAIN'}),
+            ('authServicePlugin', {'name': 'myauth', 'authSslProfile': 'myssl', 'authService': 'localhost:%d' % cls.auth_service_port}),
+            ('listener', {'host': 'localhost', 'port': cls.router_port, 'role': 'normal', 'saslPlugin': 'myauth', 'saslMechanisms': 'SCRAM-SHA-1 PLAIN'}),
             ('router', {'mode': 'standalone', 'id': 'router',
                         'saslConfigName': 'tests-mech-SCRAM',
                         'saslConfigPath': os.getcwd()})
diff --git a/tests/system_tests_qdmanage.py b/tests/system_tests_qdmanage.py
--- a/tests/system_tests_qdmanage.py
+++ b/tests/system_tests_qdmanage.py
@@ -543,30 +543,29 @@ def test_yy_query_many_links(self):
         # This qdmanage query command would fail without the fix
         # for DISPATCH-974
         query_command = 'QUERY --type=org.apache.qpid.dispatch.router.address'
-        outs = json.loads(self.run_qdmanage(query_command))
-
-        sender_addresses = 0
-        receiver_addresses = 0
-
-        for out in outs:
-            if ADDRESS_SENDER in out['name']:
-                sender_addresses += 1
-            if ADDRESS_RECEIVER in out['name']:
-                receiver_addresses += 1
+        for i in range(3):
+            sender_addresses = 0
+            receiver_addresses = 0
+            outs = json.loads(self.run_qdmanage(query_command))
+            for out in outs:
+                if ADDRESS_SENDER in out['name']:
+                    sender_addresses += 1
+                if ADDRESS_RECEIVER in out['name']:
+                    receiver_addresses += 1
+            if sender_addresses < COUNT or receiver_addresses < COUNT:
+                sleep(2)
+            else:
+                break
 
         self.assertEqual(sender_addresses, COUNT)
         self.assertEqual(receiver_addresses, COUNT)
 
         query_command = 'QUERY --type=link'
-        outs = json.loads(self.run_qdmanage(query_command))
-
-        out_links = 0
-        in_links = 0
         success = False
-
-        i = 0
-        while i < 3:
-            i += 1
+        for i in range(3):
+            out_links = 0
+            in_links = 0
+            outs = json.loads(self.run_qdmanage(query_command))
             for out in outs:
                 if out.get('owningAddr'):
                     if ADDRESS_SENDER in out['owningAddr']:
@@ -581,7 +580,6 @@ def test_yy_query_many_links(self):
             if out_links < COUNT or in_links < COUNT:
                 self.logger.log("out_links=%s, in_links=%s" % (str(out_links), str(in_links)))
                 sleep(2)
-                outs = json.loads(self.run_qdmanage(query_command))
             else:
                 self.logger.log("Test success!")
                 success = True
diff --git a/tests/system_tests_qdstat.py b/tests/system_tests_qdstat.py
--- a/tests/system_tests_qdstat.py
+++ b/tests/system_tests_qdstat.py
@@ -648,7 +648,6 @@ def test_link_priority_csv(self):
 
     def _test_links_all_routers(self, command):
         out = self.run_qdstat(command)
-        print("_test_links_all_routers out=", out)
         self.assertTrue(out.count('UTC') == 1)
         self.assertTrue(out.count('Router Links') == 2)
         self.assertTrue(out.count('inter-router') == 40)
@@ -728,17 +727,20 @@ def setUpClass(cls):
                                 'certFile': cls.ssl_file('server-certificate.pem'),
                                 'privateKeyFile': cls.ssl_file('server-private-key.pem'),
                                 'password': 'server-password'}),
-                ('listener', {'port': cls.tester.get_port()}),
-                ('listener', {'port': cls.tester.get_port(), 'sslProfile': 'server-ssl', 'authenticatePeer': 'no', 'requireSsl': 'yes'}),
-                ('listener', {'port': cls.tester.get_port(), 'sslProfile': 'server-ssl', 'authenticatePeer': 'no', 'requireSsl': 'no'}),
-                ('listener', {'port': cls.tester.get_port(), 'sslProfile': 'server-ssl', 'authenticatePeer': 'yes', 'requireSsl': 'yes',
+                ('listener', {'host': 'localhost', 'port': cls.tester.get_port()}),
+                ('listener', {'host': 'localhost', 'port': cls.tester.get_port(), 'sslProfile': 'server-ssl',
+                              'authenticatePeer': 'no', 'requireSsl': 'yes'}),
+                ('listener', {'host': 'localhost', 'port': cls.tester.get_port(), 'sslProfile': 'server-ssl',
+                              'authenticatePeer': 'no', 'requireSsl': 'no'}),
+                ('listener', {'host': 'localhost', 'port': cls.tester.get_port(), 'sslProfile': 'server-ssl',
+                              'authenticatePeer': 'yes', 'requireSsl': 'yes',
                               'saslMechanisms': 'EXTERNAL'})
             ])
             cls.router = cls.tester.qdrouterd('test-router', config)
 
         def run_qdstat(self, args, regexp=None, address=None):
             p = self.popen(
-                ['qdstat', '--bus', str(address or self.router.addresses[0]), '--ssl-disable-peer-name-verify',
+                ['qdstat', '--bus', str(address or self.router.addresses[0]),
                  '--timeout', str(system_test.TIMEOUT)] + args,
                 name='qdstat-' + self.id(), stdout=PIPE, expect=None,
                 universal_newlines=True)
@@ -778,75 +780,123 @@ def ssl_test(self, url_name, arg_names):
         def ssl_test_bad(self, url_name, arg_names):
             self.assertRaises(AssertionError, self.ssl_test, url_name, arg_names)
 
-        # Non-SSL enabled listener should fail SSL connections.
+        # qdstat -b amqp://localhost:<port> --general and makes sure
+        # the router sends back a valid response.
         def test_ssl_none(self):
             self.ssl_test('none', [])
 
+        # qdstat -b amqps://localhost:<port> --general
+        # Make sure that the command fails.
         def test_ssl_scheme_to_none(self):
             self.ssl_test_bad('none_s', [])
 
+        # qdstat -b amqp://localhost:<port> --general --ssl-certificate /path/to/client-certificate.pem
+        # Makes sure the command fails.
         def test_ssl_cert_to_none(self):
             self.ssl_test_bad('none', ['client_cert'])
 
-        # Strict SSL listener, SSL only
+        # Tries to run the following command on a listener that requires SSL (requireSsl:yes)
+        # qdstat -b amqp://localhost:<port> --general
+        # Makes sure the command fails.
         def test_ssl_none_to_strict(self):
             self.ssl_test_bad('strict', [])
 
+        # qdstat -b amqps://localhost:<port> --general
         def test_ssl_schema_to_strict(self):
-            self.ssl_test('strict_s', [])
+            self.ssl_test_bad('strict_s', [])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-certificate /path/to/client-certificate.pem
+        # --ssl-key /path/to/client-private-key.pem --ssl-password client-password'
         def test_ssl_cert_to_strict(self):
-            self.ssl_test('strict_s', ['client_cert_all'])
+            self.ssl_test_bad('strict_s', ['client_cert_all'])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-trustfile /path/to/ca-certificate.pem
         def test_ssl_trustfile_to_strict(self):
             self.ssl_test('strict_s', ['trustfile'])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-trustfile
+        # /path/to/ca-certificate.pem --ssl-certificate /path/to/client-certificate.pem
+        # --ssl-key /path/to/client-private-key.pem --ssl-password client-password
         def test_ssl_trustfile_cert_to_strict(self):
             self.ssl_test('strict_s', ['trustfile', 'client_cert_all'])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-trustfile /path/to/bad-ca-certificate.pem
+        # Send in a bad ca cert and make sure the test fails.
         def test_ssl_bad_trustfile_to_strict(self):
             self.ssl_test_bad('strict_s', ['bad_trustfile'])
 
         # Require-auth SSL listener
-
+        # qdstat -b amqp://localhost:<port> --general
+        # Send in no certs to a 'authenticatePeer': 'yes', 'requireSsl': 'yes' listener and make sure it fails.
+        # Also protocol is amqp not amqps
         def test_ssl_none_to_auth(self):
             self.ssl_test_bad('auth', [])
 
+        # qdstat -b amqps://localhost:28491 --general
+        # Send in no certs to a 'authenticatePeer': 'yes', 'requireSsl': 'yes' listener and make sure it fails.
         def test_ssl_schema_to_auth(self):
             self.ssl_test_bad('auth_s', [])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-trustfile /path/to/ca-certificate.pem'
+        # Send in just a trustfile to an 'authenticatePeer': 'yes', 'requireSsl': 'yes' listener and make sure it fails.
         def test_ssl_trustfile_to_auth(self):
             self.ssl_test_bad('auth_s', ['trustfile'])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-certificate /path/to/client-certificate.pem
+        # --ssl-key /path/to/client-private-key.pem --ssl-password client-password
+        # Without a trustfile, this test fails
         def test_ssl_cert_to_auth(self):
-            self.ssl_test('auth_s', ['client_cert_all'])
+            self.ssl_test_bad('auth_s', ['client_cert_all'])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-trustfile /path/to/ca-certificate.pem
+        # --ssl-certificate /path/to/client-certificate.pem
+        # --ssl-key /path/to/client-private-key.pem --ssl-password client-password
+        # This has everything, the test should pass.
         def test_ssl_trustfile_cert_to_auth(self):
             self.ssl_test('auth_s', ['trustfile', 'client_cert_all'])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-trustfile /path/to/bad-ca-certificate.pem
+        # --ssl-certificate /path/to/client-certificate.pem --ssl-key /path/to/client-private-key.pem
+        # --ssl-password client-password
+        # Bad trustfile should be rejected.
         def test_ssl_bad_trustfile_to_auth(self):
             self.ssl_test_bad('auth_s', ['bad_trustfile', 'client_cert_all'])
 
+        # qdstat -b amqps://localhost:<port> --general --sasl-mechanisms EXTERNAL
+        # --ssl-certificate /path/to/client-certificate.pem --ssl-key /path/to/client-private-key.pem
+        # --ssl-password client-password --ssl-trustfile /path/to/ca-certificate.pem'
         def test_ssl_cert_explicit_external_to_auth(self):
-            self.ssl_test('auth_s', ['sasl_external', 'client_cert_all'])
+            self.ssl_test('auth_s', ['sasl_external', 'client_cert_all', 'trustfile'])
 
         # Unsecured SSL listener, allows non-SSL
-
+        # qdstat -b amqp://localhost:<port> --general
         def test_ssl_none_to_unsecured(self):
             self.ssl_test('unsecured', [])
 
+        # qdstat -b amqps://localhost:<port> --general
         def test_ssl_schema_to_unsecured(self):
-            self.ssl_test('unsecured_s', [])
+            self.ssl_test_bad('unsecured_s', [])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-certificate /path/to/client-certificate.pem --ssl-key
+        # /path/to/client-private-key.pem --ssl-password client-password
+        # A trustfile is required, test will fail
         def test_ssl_cert_to_unsecured(self):
-            self.ssl_test('unsecured_s', ['client_cert_all'])
+            self.ssl_test_bad('unsecured_s', ['client_cert_all'])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-trustfile /path/to/ca-certificate.pem'
+        # Just send in the trustfile, should be all good.
         def test_ssl_trustfile_to_unsecured(self):
             self.ssl_test('unsecured_s', ['trustfile'])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-trustfile /path/to/ca-certificate.pem
+        # --ssl-certificate /path/to/client-certificate.pem --ssl-key /path/to/client-private-key.pem
+        # --ssl-password client-password
+        # We have everything, this should work.
         def test_ssl_trustfile_cert_to_unsecured(self):
             self.ssl_test('unsecured_s', ['trustfile', 'client_cert_all'])
 
+        # qdstat -b amqps://localhost:<port> --general --ssl-trustfile /path/to/bad-ca-certificate.pem']
+        # Bad trustfile, test will fail.
         def test_ssl_bad_trustfile_to_unsecured(self):
             self.ssl_test_bad('unsecured_s', ['bad_trustfile'])
 
diff --git a/tests/system_tests_ssl.py b/tests/system_tests_ssl.py
--- a/tests/system_tests_ssl.py
+++ b/tests/system_tests_ssl.py
@@ -382,6 +382,8 @@ def is_proto_allowed(self, listener_port, tls_protocol):
         url = Url("amqps://0.0.0.0:%d/$management" % listener_port)
         # Preparing SSLDomain (client cert) and SASL authentication info
         domain = SSLDomain(SSLDomain.MODE_CLIENT)
+        domain.set_trusted_ca_db(self.ssl_file('ca-certificate.pem'))
+        domain.set_peer_authentication(SSLDomain.VERIFY_PEER)
         # Enforcing given TLS protocol
         cproton.pn_ssl_domain_set_protocols(domain._domain, tls_protocol)
 
@@ -415,6 +417,8 @@ def is_ssl_sasl_client_accepted(self, listener_port, tls_protocol):
         domain.set_credentials(self.ssl_file('client-certificate.pem'),
                                self.ssl_file('client-private-key.pem'),
                                'client-password')
+        domain.set_trusted_ca_db(self.ssl_file('ca-certificate.pem'))
+        domain.set_peer_authentication(SSLDomain.VERIFY_PEER)
         # Enforcing given TLS protocol
         cproton.pn_ssl_domain_set_protocols(domain._domain, tls_protocol)
 
diff --git a/tests/system_tests_user_id.py b/tests/system_tests_user_id.py
--- a/tests/system_tests_user_id.py
+++ b/tests/system_tests_user_id.py
@@ -208,7 +208,7 @@ def setUpClass(cls):
             ('listener', {'port': cls.tester.get_port(), 'sslProfile': 'server-ssl11', 'authenticatePeer': 'yes',
                           'requireSsl': 'yes', 'saslMechanisms': 'EXTERNAL'}),
 
-            # peer is not being authenticated here. the user must "anonymous" which is what pn_transport_get_user
+            # peer is not being authenticated here. the user must be "anonymous" which is what pn_transport_get_user
             # returns
             ('listener', {'port': cls.tester.get_port(), 'sslProfile': 'server-ssl12', 'authenticatePeer': 'no',
                           'requireSsl': 'yes', 'saslMechanisms': 'ANONYMOUS'}),
@@ -242,7 +242,7 @@ def create_ssl_domain(self, ssl_options_dict, mode=SSLDomain.MODE_CLIENT):
         domain = SSLDomain(mode)
         if trustfile:
             domain.set_trusted_ca_db(str(trustfile))
-            domain.set_peer_authentication(SSLDomain.VERIFY_PEER, str(trustfile))
+        domain.set_peer_authentication(SSLDomain.VERIFY_PEER, None)
         if certificate:
             domain.set_credentials(str(certificate), str(key), str(password))
 
@@ -314,11 +314,11 @@ def test_ssl_user_id(self):
         user = node.query(type='org.apache.qpid.dispatch.connection', attribute_names=[u'user']).results[10][0]
         self.assertEqual("C=US,ST=NC,L=Raleigh,OU=Dev,O=Client,CN=127.0.0.1", str(user))
 
-        # authenticatePeer is set to 'no' in this listener, there should be no user on the connection.
+        # authenticatePeer is set to 'no' in this listener, the user should anonymous on the connection.
         addr = self.address(11).replace("amqp", "amqps")
-        node = Node.connect(addr)
+        node = Node.connect(addr, ssl_domain=domain)
         user = node.query(type='org.apache.qpid.dispatch.connection', attribute_names=[u'user']).results[11][0]
-        self.assertEqual(None, user)
+        self.assertEqual("anonymous", user)
 
         addr = self.address(12).replace("amqp", "amqps")
         node = Node.connect(addr, ssl_domain=domain)