You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2018/07/06 16:59:13 UTC

[01/11] qpid-proton git commit: PROTON-1798: [c, cpp] self-contained test scripts.

Repository: qpid-proton
Updated Branches:
  refs/heads/master ea315ff04 -> 9778eda8e


PROTON-1798: [c,cpp] self-contained test scripts.

Simplify python test scripts for C and C++, get rid of the proctest.py common
library.  Each test script is now self-contained using only standard python 2.7.


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

Branch: refs/heads/master
Commit: e2858e6afd15581d8f8b029ce76a175bb5ea41da
Parents: ea315ff
Author: Alan Conway <ac...@redhat.com>
Authored: Wed Jul 4 15:43:16 2018 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Fri Jul 6 12:16:32 2018 -0400

----------------------------------------------------------------------
 c/examples/CMakeLists.txt    |   6 +-
 c/examples/broker.c          |   4 +-
 c/examples/direct.c          |   4 +-
 c/examples/example_test.py   |  77 ++++++-------
 c/examples/receive.c         |   2 +-
 c/tests/CMakeLists.txt       |   2 -
 c/tests/fdlimit.py           |  44 +++-----
 cpp/examples/CMakeLists.txt  |   6 +-
 cpp/examples/broker.cpp      |  13 +--
 cpp/examples/example_test.py | 167 +++++++++++-----------------
 tools/python/proctest.py     | 227 --------------------------------------
 11 files changed, 121 insertions(+), 431 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/c/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/c/examples/CMakeLists.txt b/c/examples/CMakeLists.txt
index 6f732a6..17438d0 100644
--- a/c/examples/CMakeLists.txt
+++ b/c/examples/CMakeLists.txt
@@ -53,12 +53,8 @@ macro(set_search_path result)
   file(TO_NATIVE_PATH "${${result}}" ${result}) # native slash separators
 endmacro()
 
-# Add the tools directory for the 'proctest' module
-set_search_path(EXAMPLE_PYTHONPATH "${CMAKE_SOURCE_DIR}/tools/python" "$ENV{PYTHON_PATH}")
-set(EXAMPLE_ENV "PYTHONPATH=${EXAMPLE_PYTHONPATH}")
-
 add_test(
   NAME c-example-tests
-  COMMAND ${PN_ENV_SCRIPT} ${EXAMPLE_ENV} "PATH=${test_path}" ${VALGRIND_ENV} --
+  COMMAND ${PN_ENV_SCRIPT} "PATH=${test_path}" ${VALGRIND_ENV} --
           ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v
   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/c/examples/broker.c
----------------------------------------------------------------------
diff --git a/c/examples/broker.c b/c/examples/broker.c
index dcb0158..d2591df 100644
--- a/c/examples/broker.c
+++ b/c/examples/broker.c
@@ -364,8 +364,8 @@ static void handle(broker_t* b, pn_event_t* e) {
        m->start = (char*)realloc(m->start, m->size);
        recv = pn_link_recv(l, m->start, m->size);
        if (recv == PN_ABORTED) { /*  */
-         fprintf(stderr, "Message aborted\n");
-         fflush(stderr);
+         printf("Message aborted\n");
+         fflush(stdout);
          m->size = 0;           /* Forget the data we accumulated */
          pn_delivery_settle(d); /* Free the delivery so we can receive the next message */
          pn_link_flow(l, WINDOW - pn_link_credit(l)); /* Replace credit for the aborted message */

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/c/examples/direct.c
----------------------------------------------------------------------
diff --git a/c/examples/direct.c b/c/examples/direct.c
index fd0c3a4..a990663 100644
--- a/c/examples/direct.c
+++ b/c/examples/direct.c
@@ -132,8 +132,8 @@ static void handle_receive(app_data_t *app, pn_event_t* event) {
        m->start = (char*)realloc(m->start, m->size);
        recv = pn_link_recv(l, m->start, m->size);
        if (recv == PN_ABORTED) {
-         fprintf(stderr, "Message aborted\n");
-         fflush(stderr);
+         printf("Message aborted\n");
+         fflush(stdout);
          m->size = 0;           /* Forget the data we accumulated */
          pn_delivery_settle(d); /* Free the delivery so we can receive the next message */
          pn_link_flow(l, 1);    /* Replace credit for aborted message */

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/c/examples/example_test.py
----------------------------------------------------------------------
diff --git a/c/examples/example_test.py b/c/examples/example_test.py
index 25a089b..f7aa911 100644
--- a/c/examples/example_test.py
+++ b/c/examples/example_test.py
@@ -17,112 +17,99 @@
 # under the License
 #
 
-# This is a test script to run the examples and verify that they behave as expected.
+# Run the C examples and verify that they behave as expected.
+# Example executables must be in PATH
 
-import unittest, sys, time
-from proctest import *
-
-def python_cmd(name):
-    dir = os.path.dirname(__file__)
-    return [sys.executable, os.path.join(dir, "..", "..", "python", name)]
+import unittest, sys, time, re
+from subprocess import Popen, PIPE, check_output, CalledProcessError, STDOUT
 
 MESSAGES=10
 
 def receive_expect_messages(n=MESSAGES): return ''.join(['{"sequence"=%s}\n'%i for i in range(1, n+1)])
 def receive_expect_total(n=MESSAGES): return "%s messages received\n"%n
 def receive_expect(n=MESSAGES): return receive_expect_messages(n)+receive_expect_total(n)
-
 def send_expect(n=MESSAGES): return "%s messages sent and acknowledged\n" % n
 def send_abort_expect(n=MESSAGES): return "%s messages started and aborted\n" % n
 
-def wait_listening(proc):
-    m = proc.wait_re("listening on ([0-9]+)$")
-    return m.group(1), m.group(0)+"\n" # Return (port, line)
+def wait_listening(p):
+    return re.search("listening on ([0-9]+)$", p.stdout.readline()).group(1)
 
-class Broker(object):
-    def __init__(self, test):
-        self.test = test
+class Broker(Popen):
+    def __init__(self):
+        super(Broker, self).__init__(["broker", "", "0"], stdout=PIPE)
 
     def __enter__(self):
-        self.proc = self.test.proc(["broker", "", "0"])
-        self.port, _ = wait_listening(self.proc)
+        self.port = wait_listening(self)
         return self
 
     def __exit__(self, *args):
-        b = getattr(self, "proc")
-        if b:
-            if b.poll() !=  None: # Broker crashed
-                raise ProcError(b, "broker crash")
-            b.kill()
+        self.kill()
 
-class CExampleTest(ProcTestCase):
+class ExampleTest(unittest.TestCase):
 
     def runex(self, name, port, messages=MESSAGES):
         """Run an example with standard arguments, return output"""
-        return self.proc([name, "", str(port), "xtest", str(messages)]).wait_exit()
+        return check_output([name, "", str(port), "xtest", str(messages)], stderr=STDOUT)
 
     def test_send_receive(self):
         """Send first then receive"""
-        with Broker(self) as b:
+        with Broker() as b:
             self.assertEqual(send_expect(), self.runex("send", b.port))
             self.assertMultiLineEqual(receive_expect(), self.runex("receive", b.port))
 
     def test_receive_send(self):
         """Start receiving  first, then send."""
-        with Broker(self) as b:
+        with Broker() as b:
             self.assertEqual(send_expect(), self.runex("send", b.port))
             self.assertMultiLineEqual(receive_expect(), self.runex("receive", b.port))
 
     def test_send_direct(self):
         """Send to direct server"""
-        d = self.proc(["direct", "", "0"])
-        port, line = wait_listening(d)
+        d = Popen(["direct", "", "0"], stdout=PIPE)
+        port = wait_listening(d)
         self.assertEqual(send_expect(), self.runex("send", port))
-        self.assertMultiLineEqual(line+receive_expect(), d.wait_exit())
+        self.assertMultiLineEqual(receive_expect(), d.communicate()[0])
 
     def test_receive_direct(self):
         """Receive from direct server"""
-        d = self.proc(["direct", "", "0"])
-        port, line = wait_listening(d)
+        d = Popen(["direct", "", "0"], stdout=PIPE)
+        port = wait_listening(d)
         self.assertMultiLineEqual(receive_expect(), self.runex("receive", port))
-        self.assertEqual(line+"10 messages sent and acknowledged\n", d.wait_exit())
+        self.assertEqual("10 messages sent and acknowledged\n", d.communicate()[0])
 
     def test_send_abort_broker(self):
         """Sending aborted messages to a broker"""
-        with Broker(self) as b:
+        with Broker() as b:
             self.assertEqual(send_expect(), self.runex("send", b.port))
             self.assertEqual(send_abort_expect(), self.runex("send-abort", b.port))
-            b.proc.wait_re("Message aborted\n"*MESSAGES)
+            for i in xrange(MESSAGES):
+                self.assertEqual("Message aborted\n", b.stdout.readline())
             self.assertEqual(send_expect(), self.runex("send", b.port))
             expect = receive_expect_messages(MESSAGES)+receive_expect_messages(MESSAGES)+receive_expect_total(20)
             self.assertMultiLineEqual(expect, self.runex("receive", b.port, "20"))
 
     def test_send_abort_direct(self):
         """Send aborted messages to the direct server"""
-        d = self.proc(["direct", "", "0", "examples", "20"])
-        port, line = wait_listening(d)
-        expect = line
+        d = Popen(["direct", "", "0", "examples", "20"], stdout=PIPE)
+        port = wait_listening(d)
         self.assertEqual(send_expect(), self.runex("send", port))
-        expect += receive_expect_messages()
-        d.wait_re(expect)
         self.assertEqual(send_abort_expect(), self.runex("send-abort", port))
-        expect += "Message aborted\n"*MESSAGES
-        d.wait_re(expect)
         self.assertEqual(send_expect(), self.runex("send", port))
-        expect += receive_expect_messages()+receive_expect_total(20)
+        expect = receive_expect_messages() + "Message aborted\n"*MESSAGES + receive_expect_messages()+receive_expect_total(20)
         self.maxDiff = None
-        self.assertMultiLineEqual(expect, d.wait_exit())
+        self.assertMultiLineEqual(expect, d.communicate()[0])
 
     def test_send_ssl_receive(self):
         """Send with SSL, then receive"""
         try:
-            with Broker(self) as b:
+            with Broker() as b:
                 got = self.runex("send-ssl", b.port)
                 self.assertIn("secure connection:", got)
                 self.assertIn(send_expect(), got)
                 self.assertMultiLineEqual(receive_expect(), self.runex("receive", b.port))
-        except ProcError as e:
-            if e.out.startswith("error initializing SSL"):
+        except CalledProcessError as e:
+            print "FIXME", e.output
+            if e.output.startswith("error initializing SSL"):
                 print("Skipping %s: SSL not available" % self.id())
             else:
                 raise

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/c/examples/receive.c
----------------------------------------------------------------------
diff --git a/c/examples/receive.c b/c/examples/receive.c
index 8280345..c70e0d8 100644
--- a/c/examples/receive.c
+++ b/c/examples/receive.c
@@ -105,7 +105,7 @@ static bool handle(app_data_t* app, pn_event_t* event) {
        m->start = (char*)realloc(m->start, m->size);
        recv = pn_link_recv(l, m->start + oldsize, m->size);
        if (recv == PN_ABORTED) {
-         fprintf(stderr, "Message aborted\n");
+         printf("Message aborted\n");
          m->size = 0;           /* Forget the data we accumulated */
          pn_delivery_settle(d); /* Free the delivery so we can receive the next message */
          pn_link_flow(l, 1);    /* Replace credit for aborted message */

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/c/tests/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/c/tests/CMakeLists.txt b/c/tests/CMakeLists.txt
index 7283c87..c79cda4 100644
--- a/c/tests/CMakeLists.txt
+++ b/c/tests/CMakeLists.txt
@@ -78,8 +78,6 @@ if(HAS_PROACTOR)
   else(WIN32)
     set(path "$<TARGET_FILE_DIR:c-broker>:$ENV{PATH}")
   endif(WIN32)
-  # Add the tools directory for the 'proctest' module
-  set_search_path(pypath "${CMAKE_SOURCE_DIR}/tools/python" "$ENV{PYTHON_PATH}")
 
   add_test(NAME c-fdlimit-tests COMMAND ${PN_ENV_SCRIPT} -- "PATH=${path}" "PYTHONPATH=${pypath}" ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/fdlimit.py)
 endif(HAS_PROACTOR)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/c/tests/fdlimit.py
----------------------------------------------------------------------
diff --git a/c/tests/fdlimit.py b/c/tests/fdlimit.py
index 57faef8..4836140 100644
--- a/c/tests/fdlimit.py
+++ b/c/tests/fdlimit.py
@@ -18,28 +18,23 @@
 #
 from __future__ import print_function
 
-from proctest import *
+import os, sys
+from subprocess import Popen, PIPE
 
-def wait_listening(proc):
-    m = proc.wait_re("listening on ([0-9]+)$")
-    return m.group(1), m.group(0)+"\n" # Return (port, line)
+def wait_listening(p):
+    return re.search("listening on ([0-9]+)$", p.stdout.readline()).group(1)
 
-class LimitedBroker(object):
-    def __init__(self, test, fdlimit):
-        self.test = test
+class LimitedBroker(Popen):
+    def __init__(self, fdlimit):
+        super(LimitedBroker, self).__init__(["broker", "", "0"], stdout=PIPE, stderr=open(os.devnull))
         self.fdlimit = fdlimit
 
     def __enter__(self):
-        self.proc = self.test.proc(["broker", "", "0"])
-        self.port, _ = wait_listening(self.proc)
+        self.port = wait_listening(self)
         return self
 
     def __exit__(self, *args):
-        b = getattr(self, "proc")
-        if b:
-            if b.poll() not in [1, None]: # Broker crashed or got expected connection error
-                raise ProcError(b, "broker crash")
-            b.kill()
+        self.kill()
 
 # Check if we can run prlimit to control resources
 try:
@@ -50,36 +45,27 @@ except:
 
 class FdLimitTest(ProcTestCase):
 
-    def proc(self, *args, **kwargs):
-        """Skip valgrind for all processes started by this test"""
-        return super(FdLimitTest, self).proc(*args, valgrind=False, **kwargs)
-
     def test_fd_limit_broker(self):
         """Check behaviour when running out of file descriptors on accept"""
         # Not too many FDs but not too few either, some are used for system purposes.
         fdlimit = 256
-        with LimitedBroker(self, fdlimit) as b:
+        with LimitedBroker(fdlimit) as b:
             receivers = []
             # Start enough receivers to use all FDs, make sure the broker logs an error
             for i in range(fdlimit+1):
-                receivers.append(self.proc(["receive", "", b.port, str(i)]))
-
-            # Note: libuv silently swallows EMFILE/ENFILE errors so there is no error reporting.
-            # The epoll proactor will close the users connection with the EMFILE/ENFILE error
-            if "TRANSPORT_CLOSED" in b.proc.out:
-                self.assertIn("open files", b.proc.out)
+                receivers.append(Popen(["receive", "", b.port, str(i)], stdout=PIPE))
 
             # All FDs are now in use, send attempt should fail or hang
-            self.assertIn(self.proc(["send", "", b.port, "x"]).poll(), [1, None])
+            self.assertIn(Popen(["send", "", b.port, "x"], stdout=PIPE, stderr=STDOUT).poll(), [1, None])
 
             # Kill receivers to free up FDs
             for r in receivers:
                 r.kill()
             for r in receivers:
-                r.wait_exit(expect=None)
+                r.wait()
             # send/receive should succeed now
-            self.assertIn("10 messages sent", self.proc(["send", "", b.port]).wait_exit())
-            self.assertIn("10 messages received", self.proc(["receive", "", b.port]).wait_exit())
+            self.assertIn("10 messages sent", check_output(["send", "", b.port]))
+            self.assertIn("10 messages received", check_output(["receive", "", b.port]))
 
 if __name__ == "__main__":
     main()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/cpp/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/cpp/examples/CMakeLists.txt b/cpp/examples/CMakeLists.txt
index a9bde0a..8487a6b 100644
--- a/cpp/examples/CMakeLists.txt
+++ b/cpp/examples/CMakeLists.txt
@@ -113,10 +113,6 @@ macro(set_search_path result)
   file(TO_NATIVE_PATH "${${result}}" ${result}) # native slash separators
 endmacro()
 
-# Add the tools directory for the 'proctest' module
-set_search_path(EXAMPLE_PYTHONPATH "${CMAKE_SOURCE_DIR}/tools/python" "$ENV{PYTHON_PATH}")
-set(EXAMPLE_ENV "PYTHONPATH=${EXAMPLE_PYTHONPATH}")
-
 # Add a test with the correct environment to find test executables and valgrind.
 macro(add_cpp_test name)
   if(WIN32)
@@ -126,7 +122,7 @@ macro(add_cpp_test name)
   endif(WIN32)
   add_test(
     NAME ${name}
-    COMMAND ${PN_ENV_SCRIPT} ${EXAMPLE_ENV} "PATH=${test_path}" ${VALGRIND_ENV}
+    COMMAND ${PN_ENV_SCRIPT} "PATH=${test_path}" ${VALGRIND_ENV}
             "HAS_CPP11=$<$<BOOL:${HAS_ENOUGH_CPP11}>:1>" -- ${ARGN}
     )
 endmacro()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/cpp/examples/broker.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/broker.cpp b/cpp/examples/broker.cpp
index 47d6109..479ec01 100644
--- a/cpp/examples/broker.cpp
+++ b/cpp/examples/broker.cpp
@@ -44,10 +44,6 @@
 
 #if PN_CPP_HAS_STD_THREAD
 #include <thread>
-
-int hardware_concurrency() {return std::thread::hardware_concurrency();}
-#else
-int hardware_concurrency() {return 1;}
 #endif
 
 #include "fake_cpp11.hpp"
@@ -396,14 +392,9 @@ class broker {
     }
 
     void run() {
-#if PN_CPP_SUPPORTS_THREADS
-        int threads = hardware_concurrency();
-        std::cout << "starting " << threads << " listening threads\n";
-        std::cout.flush();
-        container_.run(threads);
+#if PN_CPP_HAS_STD_THREAD
+        container_.run(std::thread::hardware_concurrency());
 #else
-        std::cout << "no thread support - starting 1 listening thread\n";
-        std::cout.flush();
         container_.run();
 #endif
     }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/cpp/examples/example_test.py
----------------------------------------------------------------------
diff --git a/cpp/examples/example_test.py b/cpp/examples/example_test.py
index b9f0621..b83540f 100644
--- a/cpp/examples/example_test.py
+++ b/cpp/examples/example_test.py
@@ -17,20 +17,13 @@
 # under the License
 #
 
-# This is a test script to run the examples and verify that they behave as expected.
-
-import unittest
-import os, sys, socket, time, re, inspect
-from proctest import *
-from random import randrange
-from subprocess import Popen, PIPE, STDOUT, call
-from copy import copy
-import platform
-from os.path import dirname as dirname
-from threading import Thread, Event
-from string import Template
+# Run the C++ examples and verify that they behave as expected.
+# Example executables must be in PATH
 
-createdSASLDb = False
+import unittest, sys, time, re, shutil, os
+from subprocess import Popen, PIPE, STDOUT, check_output, check_call
+from os.path import dirname
+from string import Template
 
 def _cyrusSetup(conf_dir):
   """Write out simple SASL config.tests
@@ -41,52 +34,31 @@ def _cyrusSetup(conf_dir):
 mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS
 """)
     abs_conf_dir = os.path.abspath(conf_dir)
-    call(args=['rm','-rf',abs_conf_dir])
+    shutil.rmtree(abs_conf_dir, True)
     os.mkdir(abs_conf_dir)
     db = os.path.join(abs_conf_dir,'proton.sasldb')
     conf = os.path.join(abs_conf_dir,'proton-server.conf')
-    f = open(conf, 'w')
-    f.write(t.substitute(db=db))
-    f.close()
-
+    with open(conf, 'w') as f:
+        f.write(t.substitute(db=db))
     cmd_template = Template("echo password | ${saslpasswd} -c -p -f ${db} -u proton user")
     cmd = cmd_template.substitute(db=db, saslpasswd=saslpasswd)
-    call(args=cmd, shell=True)
-
+    check_call(args=cmd, shell=True)
     os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir
-    global createdSASLDb
-    createdSASLDb = True
 
 # Globally initialize Cyrus SASL configuration
 _cyrusSetup('sasl-conf')
 
-def wait_listening(proc):
-    m = proc.wait_re(".*listening on ([0-9]+)$")
-    return m.group(1), m.group(0)+"\n" # Return (port, line)
-
-class BrokerTestCase(ProcTestCase):
-    """
-    ExampleTest that starts a broker in setUpClass and kills it in tearDownClass.
-    Subclasses must set `broker_exe` class variable with the name of the broker executable.
-    """
-    @classmethod
-    def setUpClass(cls):
-        cls.broker = None       # In case Proc throws, create the attribute.
-        cls.broker = Proc([cls.broker_exe, "-a", "//:0"])
-        cls.port, line = wait_listening(cls.broker)
-        cls.addr = "//:%s/example" % cls.port
-
-    @classmethod
-    def tearDownClass(cls):
-        if cls.broker:
-            cls.broker.kill()
-
-    def tearDown(self):
-        b = type(self).broker
-        if b and b.poll() !=  None: # Broker crashed
-            type(self).setUpClass() # Start another for the next test.
-            raise ProcError(b, "broker crash")
-        super(BrokerTestCase, self).tearDown()
+def wait_listening(p):
+    return re.search("listening on ([0-9]+)$", p.stdout.readline()).group(1)
+
+class Broker(Popen):
+    port = None
+    def __init__(self):
+        super(Broker, self).__init__(["broker", "-a", "//:0"], stdout=PIPE, stderr=open(os.devnull))
+        Broker.port = wait_listening(self)
+        Broker.addr = "amqp://:%s/example" % self.port
+    def __enter__(self): return self
+    def __exit__(self, *args): self.kill()
 
 
 CLIENT_EXPECT="""Twas brillig, and the slithy toves => TWAS BRILLIG, AND THE SLITHY TOVES
@@ -98,51 +70,52 @@ And the mome raths outgrabe. => AND THE MOME RATHS OUTGRABE.
 def recv_expect():
     return "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)])
 
-class ContainerExampleTest(BrokerTestCase):
+class ContainerExampleTest(unittest.TestCase):
     """Run the container examples, verify they behave as expected."""
 
     broker_exe = "broker"
 
     def test_helloworld(self):
-        self.assertMultiLineEqual('Hello World!\n', self.proc(["helloworld", self.addr]).wait_exit())
+        self.assertMultiLineEqual('Hello World!\n', check_output(["helloworld", Broker.addr]))
 
     def test_simple_send_recv(self):
-        self.assertMultiLineEqual("all messages confirmed\n", self.proc(["simple_send", "-a", self.addr]).wait_exit())
-        self.assertMultiLineEqual(recv_expect(), self.proc(["simple_recv", "-a", self.addr]).wait_exit())
+        self.assertMultiLineEqual("all messages confirmed\n", check_output(["simple_send", "-a", Broker.addr]))
+        self.assertMultiLineEqual(recv_expect(), check_output(["simple_recv", "-a", Broker.addr]))
 
     def test_simple_recv_send(self):
-        # Start receiver first, then run sender"""
-        recv = self.proc(["simple_recv", "-a", self.addr])
-        self.assertMultiLineEqual("all messages confirmed\n", self.proc(["simple_send", "-a", self.addr]).wait_exit())
-        self.assertMultiLineEqual(recv_expect(), recv.wait_exit())
+        recv = Popen(["simple_recv", "-a", Broker.addr], stdout=PIPE)
+        self.assertMultiLineEqual("all messages confirmed\n", check_output(["simple_send", "-a", Broker.addr]))
+        self.assertMultiLineEqual(recv_expect(), recv.communicate()[0])
 
 
     def test_simple_send_direct_recv(self):
-        recv = self.proc(["direct_recv", "-a", "//:0"])
-        port, line = wait_listening(recv)
-        addr = "//:%s/examples" % port
-        self.assertMultiLineEqual("all messages confirmed\n",
-                                  self.proc(["simple_send", "-a", addr]).wait_exit())
-        self.assertMultiLineEqual(line+recv_expect(), recv.wait_exit())
+        recv = Popen(["direct_recv", "-a", "//:0"], stdout=PIPE)
+        addr = "//:%s/examples" % wait_listening(recv)
+        self.assertMultiLineEqual("all messages confirmed\n", check_output(["simple_send", "-a", addr]))
+        self.assertMultiLineEqual(recv_expect(), recv.communicate()[0])
+
 
     def test_simple_recv_direct_send(self):
-        send = self.proc(["direct_send", "-a", "//:0"])
-        port, line = wait_listening(send)
-        addr = "//:%s/examples" % port
-        self.assertMultiLineEqual(recv_expect(), self.proc(["simple_recv", "-a", addr]).wait_exit())
-        self.assertMultiLineEqual(line+"all messages confirmed\n", send.wait_exit())
+        send = Popen(["direct_send", "-a", "//:0"], stdout=PIPE)
+        addr = "//:%s/examples" % wait_listening(send)
+        self.assertMultiLineEqual(recv_expect(), check_output(["simple_recv", "-a", addr]))
+        self.assertMultiLineEqual("all messages confirmed\n", send.communicate()[0])
 
     def test_request_response(self):
-        server = self.proc(["server", self.addr, "example"]) # self.addr has the connection info
-        server.wait_re("connected")
-        self.assertMultiLineEqual(CLIENT_EXPECT,
-                         self.proc(["client", "-a", self.addr]).wait_exit())
+        server = Popen(["server", Broker.addr, "example"], stdout=PIPE)
+        self.assertIn("connected to", server.stdout.readline())
+        try:
+            self.assertMultiLineEqual(CLIENT_EXPECT, check_output(["client", "-a", Broker.addr]))
+        finally:
+            server.kill()
 
     def test_request_response_direct(self):
-        server = self.proc(["server_direct", "-a", "//:0"])
-        port, line = wait_listening(server);
-        addr = "//:%s/examples" % port
-        self.assertMultiLineEqual(CLIENT_EXPECT, self.proc(["client", "-a", addr]).wait_exit())
+        server = Popen(["server_direct", "-a", "//:0"], stdout=PIPE)
+        addr = "//:%s/examples" % wait_listening(server);
+        try:
+            self.assertMultiLineEqual(CLIENT_EXPECT, check_output(["client", "-a", addr]))
+        finally:
+            server.kill()
 
     def test_flow_control(self):
         want="""success: Example 1: simple credit
@@ -150,7 +123,7 @@ success: Example 2: basic drain
 success: Example 3: drain without credit
 success: Example 4: high/low watermark
 """
-        self.assertMultiLineEqual(want, self.proc(["flow_control", "--quiet"]).wait_exit())
+        self.assertMultiLineEqual(want, check_output(["flow_control", "--quiet"]))
 
     def test_encode_decode(self):
         want="""
@@ -177,17 +150,17 @@ list[int(42), boolean(0), symbol(x)]
 map{string(k1):int(42), symbol(k2):boolean(0)}
 """
         self.maxDiff = None
-        self.assertMultiLineEqual(want, self.proc(["encode_decode"]).wait_exit())
+        self.assertMultiLineEqual(want, check_output(["encode_decode"]))
 
     def test_scheduled_send_03(self):
         # Output should be a bunch of "send" lines but can't guarantee exactly how many.
-        out = self.proc(["scheduled_send_03", "-a", self.addr+"scheduled_send", "-t", "0.1", "-i", "0.001"]).wait_exit().split()
+        out = check_output(["scheduled_send_03", "-a", Broker.addr+"scheduled_send", "-t", "0.1", "-i", "0.001"]).split()
         self.assertTrue(len(out) > 0);
         self.assertEqual(["send"]*len(out), out)
 
     @unittest.skipUnless(os.getenv('HAS_CPP11'), "not a  C++11 build")
     def test_scheduled_send(self):
-        out = self.proc(["scheduled_send", "-a", self.addr+"scheduled_send", "-t", "0.1", "-i", "0.001"]).wait_exit().split()
+        out = check_output(["scheduled_send", "-a", Broker.addr+"scheduled_send", "-t", "0.1", "-i", "0.001"]).split()
         self.assertTrue(len(out) > 0);
         self.assertEqual(["send"]*len(out), out)
 
@@ -201,32 +174,25 @@ short=42 string=bar
 expected conversion_error: "unexpected type, want: uint got: int"
 expected conversion_error: "unexpected type, want: uint got: string"
 """
-        self.assertMultiLineEqual(expect, self.proc(["message_properties"]).wait_exit())
+        self.assertMultiLineEqual(expect, check_output(["message_properties"]))
 
     @unittest.skipUnless(os.getenv('HAS_CPP11'), "not a  C++11 build")
     def test_multithreaded_client(self):
-        got = self.proc(["multithreaded_client", self.addr, "examples", "10"], helgrind=True).wait_exit()
+        got = check_output(["multithreaded_client", Broker.addr, "examples", "10"])
         self.maxDiff = None
-        self.assertRegexpMatches(got, "10 messages sent and received");
+        self.assertIn("10 messages sent and received", got);
 
 #    @unittest.skipUnless(os.getenv('HAS_CPP11'), "not a  C++11 build")
     @unittest.skip("Test is unstable, will enable when fixed")
     def test_multithreaded_client_flow_control(self):
-        got = self.proc(["multithreaded_client_flow_control", self.addr, "examples", "10", "2"], helgrind=True).wait_exit()
+        got = check_output(["multithreaded_client_flow_control", Broker.addr, "examples", "10", "2"])
         self.maxDiff = None
-        self.assertRegexpMatches(got, "20 messages sent and received");
+        self.assertIn("20 messages sent and received", got);
 
-class ContainerExampleSSLTest(BrokerTestCase):
+class ContainerExampleSSLTest(unittest.TestCase):
     """Run the SSL container examples, verify they behave as expected."""
 
     broker_exe = "broker"
-    valgrind = False            # Disable for all tests, including inherited
-
-    def setUp(self):
-        super(ContainerExampleSSLTest, self).setUp()
-
-    def tearDown(self):
-        super(ContainerExampleSSLTest, self).tearDown()
 
     def ssl_certs_dir(self):
         """Absolute path to the test SSL certificates"""
@@ -234,21 +200,18 @@ class ContainerExampleSSLTest(BrokerTestCase):
 
     def test_ssl(self):
         # SSL without SASL, VERIFY_PEER_NAME
-        # Disable valgrind when using OpenSSL
-        out = self.proc(["ssl", "-c", self.ssl_certs_dir()]).wait_exit()
+        out = check_output(["ssl", "-c", self.ssl_certs_dir()])
         expect = "Server certificate identity CN=test_server\nHello World!"
         self.assertIn(expect, out)
 
     def test_ssl_no_name(self):
-        # VERIFY_PEER
-        # Disable valgrind when using OpenSSL
-        out = self.proc(["ssl", "-c", self.ssl_certs_dir(), "-v", "noname"], valgrind=False).wait_exit()
+        out = check_output(["ssl", "-c", self.ssl_certs_dir(), "-v", "noname"])
         expect = "Outgoing client connection connected via SSL.  Server certificate identity CN=test_server\nHello World!"
         self.assertIn(expect, out)
 
     def test_ssl_bad_name(self):
         # VERIFY_PEER
-        out = self.proc(["ssl", "-c", self.ssl_certs_dir(), "-v", "fail"]).wait_exit()
+        out = check_output(["ssl", "-c", self.ssl_certs_dir(), "-v", "fail"])
         expect = "Expected failure of connection with wrong peer name"
         self.assertIn(expect, out)
 
@@ -258,9 +221,9 @@ class ContainerExampleSSLTest(BrokerTestCase):
 Outgoing client connection connected via SSL.  Server certificate identity CN=test_server
 Hello World!
 """
-        # Disable valgrind when using OpenSSL
-        out = self.proc(["ssl_client_cert", self.ssl_certs_dir()]).wait_exit()
+        out = check_output(["ssl_client_cert", self.ssl_certs_dir()])
         self.assertIn(expect, out)
 
 if __name__ == "__main__":
-    unittest.main()
+    with Broker():
+        unittest.main()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e2858e6a/tools/python/proctest.py
----------------------------------------------------------------------
diff --git a/tools/python/proctest.py b/tools/python/proctest.py
deleted file mode 100644
index 6445f95..0000000
--- a/tools/python/proctest.py
+++ /dev/null
@@ -1,227 +0,0 @@
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License
-#
-
-"""Unit test library to simplify tests that start, monitor, check and report
-output from sub-processes. Provides safe port allocation for processes that
-listen on a port. Allows executables to be run under a debugging tool like
-valgrind.
-"""
-
-import unittest
-import os, sys, socket, time, re, inspect, errno, threading, tempfile
-from  random import randrange
-from subprocess import Popen, PIPE, STDOUT
-from copy import copy
-import platform
-from os.path import dirname as dirname
-
-DEFAULT_TIMEOUT=30              # Valgrind can be very slow.
-
-class ProcError(Exception):
-    """An exception that displays failed process output"""
-    def __init__(self, proc, what="bad exit status"):
-        self.out = proc.out.strip()
-        returncode = getattr(proc, 'returncode') # Can be missing in some cases
-        msg = "%s (exit=%s) command:\n%s" % (what, returncode, " ".join(proc.args))
-        if self.out:
-            msg += "\nvvvvvvvvvvvvvvvv\n%s\n^^^^^^^^^^^^^^^^" % self.out
-        else:
-            msg += "\n<<no output>>"
-        super(ProcError, self, ).__init__(msg)
-
-class NotFoundError(ProcError):
-    pass
-
-class Proc(Popen):
-    """Subclass of suprocess.Popen that stores its output and can scan it for a
-    'ready' pattern' Use self.out to access output (combined stdout and stderr).
-    You can't set the Popen stdout and stderr arguments, they will be overwritten.
-    """
-
-    @property
-    def out(self):
-        self._out.seek(0)
-        return self._out.read()
-
-    def __init__(self, args, valgrind=True, helgrind=False, **kwargs):
-        """Start an example process"""
-        self.args = list(args)
-        self.kwargs = kwargs
-        self._out = tempfile.TemporaryFile(mode='w+')
-        valgrind_exe = valgrind and os.getenv("VALGRIND")
-        if valgrind_exe:
-            # run valgrind for speed, not for detailed information
-            vg = [valgrind_exe]
-            if helgrind:
-                vg += ["--tool=helgrind", "--quiet", "--error-exitcode=42"]
-            else:
-                vg += ["--tool=memcheck"] + os.getenv("VALGRIND_ARGS").split(' ')
-            self.args = vg + self.args
-        if os.getenv("PROCTEST_VERBOSE"):
-            sys.stderr.write("\n== running == "+" ".join(self.args)+"\n")
-        try:
-            Popen.__init__(self, self.args, stdout=self._out, stderr=STDOUT, **kwargs)
-        except OSError as e:
-            if e.errno == errno.ENOENT:
-                raise NotFoundError(self, str(e))
-            raise ProcError(self, str(e))
-        except Exception as e:
-            raise ProcError(self, str(e))
-
-    def __del__(self):
-        self._out.close()
-
-    def kill(self):
-        try:
-            if self.poll() is None:
-                Popen.kill(self)
-        except:
-            pass                # Already exited.
-        return self.out
-
-    def wait_exit(self, timeout=DEFAULT_TIMEOUT, expect=0):
-        """Wait for process to exit, return output. Raise ProcError  on failure."""
-        t = threading.Thread(target=self.wait)
-        t.start()
-        t.join(timeout)
-        if self.poll() is None:      # Still running
-            self.kill()
-            raise ProcError(self, "still running after %ss" % timeout)
-        if expect is not None and self.poll() != expect:
-            raise ProcError(self)
-        return self.out
-
-    def wait_re(self, regexp, timeout=DEFAULT_TIMEOUT):
-        """
-        Wait for regexp to appear in the output, returns the re.search match result.
-        The target process should flush() important output to ensure it appears.
-        """
-        if timeout:
-            deadline = time.time() + timeout
-        while timeout is None or time.time() < deadline:
-            match = re.search(regexp, self.out)
-            if match:
-                return match
-            if self.poll() is not None:
-                raise ProcError(self, "process exited while waiting for '%s'" % (regexp))
-            time.sleep(0.01)    # Not very efficient
-        raise ProcError(self, "gave up waiting for '%s' after %ss" % (regexp, timeout))
-
-def _tc_missing(attr):
-    return not hasattr(unittest.TestCase, attr)
-
-class ProcTestCase(unittest.TestCase):
-    """TestCase that manages started processes
-
-    Also roughly provides setUpClass() and tearDownClass() and other features
-    missing in python 2.6. If subclasses override setUp() or tearDown() they
-    *must* call the superclass.
-    """
-
-    def setUp(self):
-        super(ProcTestCase, self).setUp()
-        self.procs = []
-
-    def tearDown(self):
-        for p in self.procs:
-            p.kill()
-        super(ProcTestCase, self).tearDown()
-
-    # Default value for valgrind= in proc() function if not explicitly set.
-    # Override by setting a "valgrind" member in subclass or instance.
-    valgrind=True
-
-    def proc(self, *args, **kwargs):
-        """Return a Proc() that will be automatically killed on teardown"""
-        if 'valgrind' in kwargs:
-            p = Proc(*args, **kwargs)
-        else:
-            p = Proc(*args, valgrind=self.valgrind, **kwargs)
-        self.procs.append(p)
-        return p
-
-    if _tc_missing('setUpClass') and _tc_missing('tearDownClass'):
-
-        @classmethod
-        def setUpClass(cls):
-            pass
-
-        @classmethod
-        def tearDownClass(cls):
-            pass
-
-        def setUp(self):
-            super(ProcTestCase, self).setUp()
-            cls = type(self)
-            if not hasattr(cls, '_setup_class_count'): # First time
-                def is_test(m):
-                    return inspect.ismethod(m) and m.__name__.startswith('test_')
-                cls._setup_class_count = len(inspect.getmembers(cls, predicate=is_test))
-                cls.setUpClass()
-            self.procs = []
-
-        def tearDown(self):
-            self.assertTrue(self._setup_class_count > 0)
-            self._setup_class_count -=  1
-            if self._setup_class_count == 0:
-                type(self).tearDownClass()
-            for p in self.procs:
-                p.kill()
-            super(ProcTestCase, self).tearDown()
-
-    if _tc_missing('assertIn'):
-        def assertIn(self, a, b):
-            self.assertTrue(a in b, "%r not in %r" % (a, b))
-
-    if _tc_missing('assertMultiLineEqual'):
-        def assertMultiLineEqual(self, a, b):
-            self.assertEqual(a, b)
-
-from functools import reduce
-
-#### Skip decorators missing in python 2.6
-
-def _id(obj):
-    return obj
-
-from functools import wraps
-
-def skip(reason):
-    def decorator(test):
-       @wraps(test)
-       def skipper(*args, **kwargs):
-           print("skipped %s: %s" % (test.__name__, reason))
-       return skipper
-    return decorator
-
-def skipIf(cond, reason):
-    if cond: return skip(reason)
-    else: return _id
-
-def skipUnless(cond, reason):
-    if not cond: return skip(reason)
-    else: return _id
-
-if not hasattr(unittest, 'skip'): unittest.skip = skip
-if not hasattr(unittest, 'skipIf'): unittest.skipIf = skipIf
-if not hasattr(unittest, 'skipUnless'): unittest.skipUnless = skipUnless
-
-from unittest import main
-if __name__ == "__main__":
-    main()


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[02/11] qpid-proton git commit: PROTON-1798: [c, cpp] update example drivers to work with python 3

Posted by ac...@apache.org.
PROTON-1798: [c,cpp] update example drivers to work with python 3


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

Branch: refs/heads/master
Commit: b41f60d46cb81909c349ef705c0b5ccccf402231
Parents: e2858e6
Author: Alan Conway <ac...@redhat.com>
Authored: Thu Jul 5 14:25:40 2018 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Fri Jul 6 12:20:32 2018 -0400

----------------------------------------------------------------------
 c/examples/example_test.py   | 78 +++++++++++++++++++---------------
 c/tests/fdlimit.py           |  2 +-
 cpp/examples/example_test.py | 88 ++++++++++++++++++++++-----------------
 3 files changed, 94 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/b41f60d4/c/examples/example_test.py
----------------------------------------------------------------------
diff --git a/c/examples/example_test.py b/c/examples/example_test.py
index f7aa911..2cf87d8 100644
--- a/c/examples/example_test.py
+++ b/c/examples/example_test.py
@@ -21,7 +21,31 @@
 # Example executables must be in PATH
 
 import unittest, sys, time, re
-from subprocess import Popen, PIPE, check_output, CalledProcessError, STDOUT
+
+import subprocess
+
+class Server(subprocess.Popen):
+    def __init__(self, *args, **kwargs):
+        self.kill_me = kwargs.pop('kill_me', False)
+        kwargs.update({'universal_newlines': True,
+                       'stdout': subprocess.PIPE,
+                       'stderr': subprocess.STDOUT})
+        super(Server, self).__init__(*args, **kwargs)
+
+    def __enter__(self):
+        line = self.stdout.readline()
+        self.port = re.search("listening on ([0-9]+)$", line).group(1)
+        return self
+
+    def __exit__(self, *args):
+        if self.kill_me:
+            self.kill()
+            self.stdout.close() # Doesn't get closed if killed
+        self.wait()
+
+def check_output(*args, **kwargs):
+    kwargs.update({'universal_newlines': True})
+    return subprocess.check_output(*args, **kwargs)
 
 MESSAGES=10
 
@@ -31,25 +55,15 @@ def receive_expect(n=MESSAGES): return receive_expect_messages(n)+receive_expect
 def send_expect(n=MESSAGES): return "%s messages sent and acknowledged\n" % n
 def send_abort_expect(n=MESSAGES): return "%s messages started and aborted\n" % n
 
-def wait_listening(p):
-    return re.search("listening on ([0-9]+)$", p.stdout.readline()).group(1)
-
-class Broker(Popen):
+class Broker(Server):
     def __init__(self):
-        super(Broker, self).__init__(["broker", "", "0"], stdout=PIPE)
-
-    def __enter__(self):
-        self.port = wait_listening(self)
-        return self
-
-    def __exit__(self, *args):
-        self.kill()
+        super(Broker, self).__init__(["broker", "", "0"], kill_me=True)
 
 class ExampleTest(unittest.TestCase):
 
     def runex(self, name, port, messages=MESSAGES):
         """Run an example with standard arguments, return output"""
-        return check_output([name, "", str(port), "xtest", str(messages)], stderr=STDOUT)
+        return check_output([name, "", port, "xtest", str(messages)])
 
     def test_send_receive(self):
         """Send first then receive"""
@@ -65,24 +79,22 @@ class ExampleTest(unittest.TestCase):
 
     def test_send_direct(self):
         """Send to direct server"""
-        d = Popen(["direct", "", "0"], stdout=PIPE)
-        port = wait_listening(d)
-        self.assertEqual(send_expect(), self.runex("send", port))
-        self.assertMultiLineEqual(receive_expect(), d.communicate()[0])
+        with Server(["direct", "", "0"]) as d:
+            self.assertEqual(send_expect(), self.runex("send", d.port))
+            self.assertMultiLineEqual(receive_expect(), d.communicate()[0])
 
     def test_receive_direct(self):
         """Receive from direct server"""
-        d = Popen(["direct", "", "0"], stdout=PIPE)
-        port = wait_listening(d)
-        self.assertMultiLineEqual(receive_expect(), self.runex("receive", port))
-        self.assertEqual("10 messages sent and acknowledged\n", d.communicate()[0])
+        with Server(["direct", "", "0"]) as d:
+            self.assertMultiLineEqual(receive_expect(), self.runex("receive", d.port))
+            self.assertEqual("10 messages sent and acknowledged\n", d.communicate()[0])
 
     def test_send_abort_broker(self):
         """Sending aborted messages to a broker"""
         with Broker() as b:
             self.assertEqual(send_expect(), self.runex("send", b.port))
             self.assertEqual(send_abort_expect(), self.runex("send-abort", b.port))
-            for i in xrange(MESSAGES):
+            for i in range(MESSAGES):
                 self.assertEqual("Message aborted\n", b.stdout.readline())
             self.assertEqual(send_expect(), self.runex("send", b.port))
             expect = receive_expect_messages(MESSAGES)+receive_expect_messages(MESSAGES)+receive_expect_total(20)
@@ -90,14 +102,13 @@ class ExampleTest(unittest.TestCase):
 
     def test_send_abort_direct(self):
         """Send aborted messages to the direct server"""
-        d = Popen(["direct", "", "0", "examples", "20"], stdout=PIPE)
-        port = wait_listening(d)
-        self.assertEqual(send_expect(), self.runex("send", port))
-        self.assertEqual(send_abort_expect(), self.runex("send-abort", port))
-        self.assertEqual(send_expect(), self.runex("send", port))
-        expect = receive_expect_messages() + "Message aborted\n"*MESSAGES + receive_expect_messages()+receive_expect_total(20)
-        self.maxDiff = None
-        self.assertMultiLineEqual(expect, d.communicate()[0])
+        with Server(["direct", "", "0", "examples", "20"]) as d:
+            self.assertEqual(send_expect(), self.runex("send", d.port))
+            self.assertEqual(send_abort_expect(), self.runex("send-abort", d.port))
+            self.assertEqual(send_expect(), self.runex("send", d.port))
+            expect = receive_expect_messages() + "Message aborted\n"*MESSAGES + receive_expect_messages()+receive_expect_total(20)
+            self.maxDiff = None
+            self.assertMultiLineEqual(expect, d.communicate()[0])
 
     def test_send_ssl_receive(self):
         """Send with SSL, then receive"""
@@ -107,9 +118,8 @@ class ExampleTest(unittest.TestCase):
                 self.assertIn("secure connection:", got)
                 self.assertIn(send_expect(), got)
                 self.assertMultiLineEqual(receive_expect(), self.runex("receive", b.port))
-        except CalledProcessError as e:
-            print "FIXME", e.output
-            if e.output.startswith("error initializing SSL"):
+        except subprocess.CalledProcessError as e:
+            if e.output.startswith(b"error initializing SSL"):
                 print("Skipping %s: SSL not available" % self.id())
             else:
                 raise

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/b41f60d4/c/tests/fdlimit.py
----------------------------------------------------------------------
diff --git a/c/tests/fdlimit.py b/c/tests/fdlimit.py
index 4836140..e5cedac 100644
--- a/c/tests/fdlimit.py
+++ b/c/tests/fdlimit.py
@@ -22,7 +22,7 @@ import os, sys
 from subprocess import Popen, PIPE
 
 def wait_listening(p):
-    return re.search("listening on ([0-9]+)$", p.stdout.readline()).group(1)
+    return re.search(b"listening on ([0-9]+)$", p.stdout.readline()).group(1)
 
 class LimitedBroker(Popen):
     def __init__(self, fdlimit):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/b41f60d4/cpp/examples/example_test.py
----------------------------------------------------------------------
diff --git a/cpp/examples/example_test.py b/cpp/examples/example_test.py
index b83540f..e287ba5 100644
--- a/cpp/examples/example_test.py
+++ b/cpp/examples/example_test.py
@@ -21,10 +21,40 @@
 # Example executables must be in PATH
 
 import unittest, sys, time, re, shutil, os
-from subprocess import Popen, PIPE, STDOUT, check_output, check_call
 from os.path import dirname
 from string import Template
 
+import subprocess
+
+class Server(subprocess.Popen):
+    def __init__(self, *args, **kwargs):
+        self.port = None
+        self.kill_me = kwargs.pop('kill_me', False)
+        kwargs.update({'universal_newlines': True,
+                       'stdout': subprocess.PIPE,
+                       'stderr': subprocess.STDOUT})
+        super(Server, self).__init__(*args, **kwargs)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args):
+        if self.kill_me:
+            self.kill()
+            self.stdout.close() # Doesn't get closed if killed
+        self.wait()
+
+    @property
+    def addr(self):
+        if not self.port:
+            line = self.stdout.readline()
+            self.port = re.search("listening on ([0-9]+)$", line).group(1)
+        return ":%s/example" % self.port
+
+def check_output(*args, **kwargs):
+    kwargs.update({'universal_newlines': True})
+    return subprocess.check_output(*args, **kwargs)
+
 def _cyrusSetup(conf_dir):
   """Write out simple SASL config.tests
   """
@@ -42,24 +72,18 @@ mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS
         f.write(t.substitute(db=db))
     cmd_template = Template("echo password | ${saslpasswd} -c -p -f ${db} -u proton user")
     cmd = cmd_template.substitute(db=db, saslpasswd=saslpasswd)
-    check_call(args=cmd, shell=True)
+    check_output(args=cmd, shell=True)
     os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir
 
 # Globally initialize Cyrus SASL configuration
 _cyrusSetup('sasl-conf')
 
 def wait_listening(p):
-    return re.search("listening on ([0-9]+)$", p.stdout.readline()).group(1)
-
-class Broker(Popen):
-    port = None
-    def __init__(self):
-        super(Broker, self).__init__(["broker", "-a", "//:0"], stdout=PIPE, stderr=open(os.devnull))
-        Broker.port = wait_listening(self)
-        Broker.addr = "amqp://:%s/example" % self.port
-    def __enter__(self): return self
-    def __exit__(self, *args): self.kill()
+    return re.search(b"listening on ([0-9]+)$", p.stdout.readline()).group(1)
 
+class Broker(Server):
+  def __init__(self):
+    super(Broker, self).__init__(["broker", "-a", "//:0"], kill_me=True)
 
 CLIENT_EXPECT="""Twas brillig, and the slithy toves => TWAS BRILLIG, AND THE SLITHY TOVES
 Did gire and gymble in the wabe. => DID GIRE AND GYMBLE IN THE WABE.
@@ -73,49 +97,36 @@ def recv_expect():
 class ContainerExampleTest(unittest.TestCase):
     """Run the container examples, verify they behave as expected."""
 
-    broker_exe = "broker"
-
     def test_helloworld(self):
-        self.assertMultiLineEqual('Hello World!\n', check_output(["helloworld", Broker.addr]))
+      self.assertMultiLineEqual('Hello World!\n', check_output(["helloworld", Broker.addr]))
 
     def test_simple_send_recv(self):
         self.assertMultiLineEqual("all messages confirmed\n", check_output(["simple_send", "-a", Broker.addr]))
         self.assertMultiLineEqual(recv_expect(), check_output(["simple_recv", "-a", Broker.addr]))
 
     def test_simple_recv_send(self):
-        recv = Popen(["simple_recv", "-a", Broker.addr], stdout=PIPE)
+        recv = Server(["simple_recv", "-a", Broker.addr])
         self.assertMultiLineEqual("all messages confirmed\n", check_output(["simple_send", "-a", Broker.addr]))
         self.assertMultiLineEqual(recv_expect(), recv.communicate()[0])
 
-
     def test_simple_send_direct_recv(self):
-        recv = Popen(["direct_recv", "-a", "//:0"], stdout=PIPE)
-        addr = "//:%s/examples" % wait_listening(recv)
-        self.assertMultiLineEqual("all messages confirmed\n", check_output(["simple_send", "-a", addr]))
+        recv = Server(["direct_recv", "-a", "//:0"])
+        self.assertMultiLineEqual("all messages confirmed\n", check_output(["simple_send", "-a", recv.addr]))
         self.assertMultiLineEqual(recv_expect(), recv.communicate()[0])
 
-
     def test_simple_recv_direct_send(self):
-        send = Popen(["direct_send", "-a", "//:0"], stdout=PIPE)
-        addr = "//:%s/examples" % wait_listening(send)
-        self.assertMultiLineEqual(recv_expect(), check_output(["simple_recv", "-a", addr]))
+        send = Server(["direct_send", "-a", "//:0"])
+        self.assertMultiLineEqual(recv_expect(), check_output(["simple_recv", "-a", send.addr]))
         self.assertMultiLineEqual("all messages confirmed\n", send.communicate()[0])
 
     def test_request_response(self):
-        server = Popen(["server", Broker.addr, "example"], stdout=PIPE)
-        self.assertIn("connected to", server.stdout.readline())
-        try:
+        with Server(["server", Broker.addr, "example"], kill_me=True) as server:
+            self.assertIn("connected to", server.stdout.readline())
             self.assertMultiLineEqual(CLIENT_EXPECT, check_output(["client", "-a", Broker.addr]))
-        finally:
-            server.kill()
 
     def test_request_response_direct(self):
-        server = Popen(["server_direct", "-a", "//:0"], stdout=PIPE)
-        addr = "//:%s/examples" % wait_listening(server);
-        try:
-            self.assertMultiLineEqual(CLIENT_EXPECT, check_output(["client", "-a", addr]))
-        finally:
-            server.kill()
+        with Server(["server_direct", "-a", "//:0"], kill_me=True) as server:
+            self.assertMultiLineEqual(CLIENT_EXPECT, check_output(["client", "-a", server.addr]))
 
     def test_flow_control(self):
         want="""success: Example 1: simple credit
@@ -192,8 +203,6 @@ expected conversion_error: "unexpected type, want: uint got: string"
 class ContainerExampleSSLTest(unittest.TestCase):
     """Run the SSL container examples, verify they behave as expected."""
 
-    broker_exe = "broker"
-
     def ssl_certs_dir(self):
         """Absolute path to the test SSL certificates"""
         return os.path.join(dirname(sys.argv[0]), "ssl-certs")
@@ -225,5 +234,6 @@ Hello World!
         self.assertIn(expect, out)
 
 if __name__ == "__main__":
-    with Broker():
-        unittest.main()
+    with Broker() as b:
+      Broker.addr = b.addr
+      unittest.main()


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[09/11] qpid-proton git commit: PROTON-1885: [python] move tests/python to python/tests

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/interop.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/interop.py b/python/tests/proton_tests/interop.py
new file mode 100644
index 0000000..fe62c02
--- /dev/null
+++ b/python/tests/proton_tests/interop.py
@@ -0,0 +1,147 @@
+#
+# 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.
+#
+
+from proton import *
+from . import common
+import os
+
+
+def find_test_interop_dir():
+    """Find the common tests directory relative to this script"""
+    from os.path import dirname, join, abspath, isdir
+    f = dirname(dirname(dirname(dirname(abspath(__file__)))))
+    f = join(f, "tests", "interop")
+    if not isdir(f):
+        raise Exception("Cannot find tests/interop directory from "+__file__)
+    return f
+
+test_interop_dir=find_test_interop_dir()
+
+class InteropTest(common.Test):
+
+    def setUp(self):
+        self.data = Data()
+        self.message = Message()
+
+    def tearDown(self):
+        self.data = None
+
+    def get_data(self, name):
+        filename = os.path.join(test_interop_dir, name+".amqp")
+        f = open(filename,"rb")
+        try: return f.read()
+        finally: f.close()
+
+    def decode_data(self, encoded):
+        buffer = encoded
+        while buffer:
+            n = self.data.decode(buffer)
+            buffer = buffer[n:]
+        self.data.rewind()
+
+    def decode_data_file(self, name):
+        encoded = self.get_data(name)
+        self.decode_data(encoded)
+        encoded_size = self.data.encoded_size()
+        # Re-encode and verify pre-computed and actual encoded size match.
+        reencoded = self.data.encode()
+        assert encoded_size == len(reencoded), "%d != %d" % (encoded_size, len(reencoded))
+        # verify round trip bytes
+        assert reencoded == encoded, "Value mismatch: %s != %s" % (reencoded, encoded)
+
+    def decode_message_file(self, name):
+        self.message.decode(self.get_data(name))
+        body = self.message.body
+        if str(type(body)) == "<type 'org.apache.qpid.proton.amqp.Binary'>":
+            body = body.array.tostring()
+        self.decode_data(body)
+
+    def assert_next(self, type, value):
+        next_type = self.data.next()
+        assert next_type == type, "Type mismatch: %s != %s"%(
+            Data.type_names[next_type], Data.type_names[type])
+        next_value = self.data.get_object()
+        assert next_value == value, "Value mismatch: %s != %s"%(next_value, value)
+
+    def test_message(self):
+        self.decode_message_file("message")
+        self.assert_next(Data.STRING, "hello")
+        assert self.data.next() is None
+
+    def test_primitives(self):
+        self.decode_data_file("primitives")
+        self.assert_next(Data.BOOL, True)
+        self.assert_next(Data.BOOL, False)
+        self.assert_next(Data.UBYTE, 42)
+        self.assert_next(Data.USHORT, 42)
+        self.assert_next(Data.SHORT, -42)
+        self.assert_next(Data.UINT, 12345)
+        self.assert_next(Data.INT, -12345)
+        self.assert_next(Data.ULONG, 12345)
+        self.assert_next(Data.LONG, -12345)
+        self.assert_next(Data.FLOAT, 0.125)
+        self.assert_next(Data.DOUBLE, 0.125)
+        assert self.data.next() is None
+
+    def test_strings(self):
+        self.decode_data_file("strings")
+        self.assert_next(Data.BINARY, b"abc\0defg")
+        self.assert_next(Data.STRING, "abcdefg")
+        self.assert_next(Data.SYMBOL, "abcdefg")
+        self.assert_next(Data.BINARY, b"")
+        self.assert_next(Data.STRING, "")
+        self.assert_next(Data.SYMBOL, "")
+        assert self.data.next() is None
+
+    def test_described(self):
+        self.decode_data_file("described")
+        self.assert_next(Data.DESCRIBED, Described("foo-descriptor", "foo-value"))
+        self.data.exit()
+
+        assert self.data.next() == Data.DESCRIBED
+        self.data.enter()
+        self.assert_next(Data.INT, 12)
+        self.assert_next(Data.INT, 13)
+        self.data.exit()
+
+        assert self.data.next() is None
+
+    def test_described_array(self):
+        self.decode_data_file("described_array")
+        self.assert_next(Data.ARRAY, Array("int-array", Data.INT, *range(0,10)))
+
+    def test_arrays(self):
+        self.decode_data_file("arrays")
+        self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.INT, *range(0,100)))
+        self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.STRING, *["a", "b", "c"]))
+        self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.INT))
+        assert self.data.next() is None
+
+    def test_lists(self):
+        self.decode_data_file("lists")
+        self.assert_next(Data.LIST, [32, "foo", True])
+        self.assert_next(Data.LIST, [])
+        assert self.data.next() is None
+
+    def test_maps(self):
+        self.decode_data_file("maps")
+        self.assert_next(Data.MAP, {"one":1, "two":2, "three":3 })
+        self.assert_next(Data.MAP, {1:"one", 2:"two", 3:"three"})
+        self.assert_next(Data.MAP, {})
+        assert self.data.next() is None

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/message.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/message.py b/python/tests/proton_tests/message.py
new file mode 100644
index 0000000..26a3dd2
--- /dev/null
+++ b/python/tests/proton_tests/message.py
@@ -0,0 +1,275 @@
+#
+# 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.
+#
+
+import os
+from . import common
+from proton import *
+from uuid import uuid4
+
+class Test(common.Test):
+
+  def setUp(self):
+    self.msg = Message()
+
+  def tearDown(self):
+    self.msg = None
+
+
+class AccessorsTest(Test):
+
+  def _test(self, name, default, values):
+    d = getattr(self.msg, name)
+    assert d == default, (d, default)
+    for v in values:
+      setattr(self.msg, name, v)
+      gotten = getattr(self.msg, name)
+      assert gotten == v, gotten
+
+  def _test_symbol(self, name):
+    self._test(name, symbol(None), (symbol(u"abc.123.#$%"), symbol(u"hello.world")))
+
+  def _test_str(self, name):
+    self._test(name, None, (u"asdf", u"fdsa", u""))
+
+  def _test_time(self, name):
+    self._test(name, 0, (0, 123456789, 987654321))
+
+  def testId(self):
+    self._test("id", None, ("bytes", None, 123, u"string", uuid4()))
+
+  def testCorrelationId(self):
+    self._test("correlation_id", None, ("bytes", None, 123, u"string", uuid4()))
+
+  def testDurable(self):
+    self._test("durable", False, (True, False))
+
+  def testPriority(self):
+    self._test("priority", Message.DEFAULT_PRIORITY, range(0, 255))
+
+  def testTtl(self):
+    self._test("ttl", 0, range(12345, 54321))
+
+  def testFirstAcquirer(self):
+    self._test("first_acquirer", False, (True, False))
+
+  def testDeliveryCount(self):
+    self._test("delivery_count", 0, range(0, 1024))
+
+  def testUserId(self):
+    self._test("user_id", b"", (b"asdf", b"fdsa", b"asd\x00fdsa", b""))
+
+  def testAddress(self):
+    self._test_str("address")
+
+  def testSubject(self):
+    self._test_str("subject")
+
+  def testReplyTo(self):
+    self._test_str("reply_to")
+
+  def testContentType(self):
+    self._test_symbol("content_type")
+
+  def testContentEncoding(self):
+    self._test_symbol("content_encoding")
+
+  def testExpiryTime(self):
+    self._test_time("expiry_time")
+
+  def testCreationTime(self):
+    self._test_time("creation_time")
+
+  def testGroupId(self):
+    self._test_str("group_id")
+
+  def testGroupSequence(self):
+    self._test("group_sequence", 0, (0, -10, 10, 20, -20))
+
+  def testReplyToGroupId(self):
+    self._test_str("reply_to_group_id")
+
+class CodecTest(Test):
+
+  def testProperties(self):
+    self.msg.properties = {}
+    self.msg.properties['key'] = 'value'
+    data = self.msg.encode()
+
+    msg2 = Message()
+    msg2.decode(data)
+
+    assert msg2.properties['key'] == 'value', msg2.properties['key']
+
+  def testRoundTrip(self):
+    self.msg.id = "asdf"
+    self.msg.correlation_id = uuid4()
+    self.msg.ttl = 3
+    self.msg.priority = 100
+    self.msg.address = "address"
+    self.msg.subject = "subject"
+    self.msg.body = 'Hello World!'
+
+    data = self.msg.encode()
+
+    msg2 = Message()
+    msg2.decode(data)
+
+    assert self.msg.id == msg2.id, (self.msg.id, msg2.id)
+    assert self.msg.correlation_id == msg2.correlation_id, (self.msg.correlation_id, msg2.correlation_id)
+    assert self.msg.ttl == msg2.ttl, (self.msg.ttl, msg2.ttl)
+    assert self.msg.priority == msg2.priority, (self.msg.priority, msg2.priority)
+    assert self.msg.address == msg2.address, (self.msg.address, msg2.address)
+    assert self.msg.subject == msg2.subject, (self.msg.subject, msg2.subject)
+    assert self.msg.body == msg2.body, (self.msg.body, msg2.body)
+
+  def testExpiryEncodeAsNull(self):
+    self.msg.group_id = "A" # Force creation and expiry fields to be present
+    data = self.msg.encode()
+
+    decoder = Data()
+
+    # Skip past the headers
+    consumed = decoder.decode(data)
+    decoder.clear()
+    data = data[consumed:]
+
+    decoder.decode(data)
+    dproperties = decoder.get_py_described()
+    # Check we've got the correct described list
+    assert dproperties.descriptor == 0x73, (dproperties.descriptor)
+
+    properties = dproperties.value
+    assert properties[8] == None, properties[8]
+
+  def testCreationEncodeAsNull(self):
+    self.msg.group_id = "A" # Force creation and expiry fields to be present
+    data = self.msg.encode()
+
+    decoder = Data()
+
+    # Skip past the headers
+    consumed = decoder.decode(data)
+    decoder.clear()
+    data = data[consumed:]
+
+    decoder.decode(data)
+    dproperties = decoder.get_py_described()
+    # Check we've got the correct described list
+    assert dproperties.descriptor == 0x73, (dproperties.descriptor)
+
+    properties = dproperties.value
+    assert properties[9] == None, properties[9]
+
+  def testGroupSequenceEncodeAsNull(self):
+    self.msg.reply_to_group_id = "R" # Force group_id and group_sequence fields to be present
+    data = self.msg.encode()
+
+    decoder = Data()
+
+    # Skip past the headers
+    consumed = decoder.decode(data)
+    decoder.clear()
+    data = data[consumed:]
+
+    decoder.decode(data)
+    dproperties = decoder.get_py_described()
+    # Check we've got the correct described list
+    assert dproperties.descriptor == 0x73, (dproperties.descriptor)
+
+    properties = dproperties.value
+    assert properties[10] == None, properties[10]
+    assert properties[11] == None, properties[11]
+
+  def testGroupSequenceEncodeAsNonNull(self):
+    self.msg.group_id = "G"
+    self.msg.reply_to_group_id = "R" # Force group_id and group_sequence fields to be present
+    data = self.msg.encode()
+
+    decoder = Data()
+
+    # Skip past the headers
+    consumed = decoder.decode(data)
+    decoder.clear()
+    data = data[consumed:]
+
+    decoder.decode(data)
+    dproperties = decoder.get_py_described()
+    # Check we've got the correct described list
+    assert dproperties.descriptor == 0x73, (dproperties.descriptor)
+
+    properties = dproperties.value
+    assert properties[10] == 'G', properties[10]
+    assert properties[11] == 0, properties[11]
+
+  def testDefaultCreationExpiryDecode(self):
+    # This is a message with everything filled explicitly as null or zero in LIST32 HEADER and PROPERTIES lists
+    data = b'\x00\x53\x70\xd0\x00\x00\x00\x0a\x00\x00\x00\x05\x42\x40\x40\x42\x52\x00\x00\x53\x73\xd0\x00\x00\x00\x12\x00\x00\x00\x0d\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x52\x00\x40'
+    msg2 = Message()
+    msg2.decode(data)
+    assert msg2.expiry_time == 0, (msg2.expiry_time)
+    assert msg2.creation_time == 0, (msg2.creation_time)
+
+    # The same message with LIST8s instead
+    data = b'\x00\x53\x70\xc0\x07\x05\x42\x40\x40\x42\x52\x00\x00\x53\x73\xc0\x0f\x0d\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x52\x00\x40'
+    msg3 = Message()
+    msg3.decode(data)
+    assert msg2.expiry_time == 0, (msg2.expiry_time)
+    assert msg2.creation_time == 0, (msg2.creation_time)
+
+    # Minified message with zero length HEADER and PROPERTIES lists
+    data = b'\x00\x53\x70\x45' b'\x00\x53\x73\x45'
+    msg4 = Message()
+    msg4.decode(data)
+    assert msg2.expiry_time == 0, (msg2.expiry_time)
+    assert msg2.creation_time == 0, (msg2.creation_time)
+
+  def testDefaultPriorityEncode(self):
+    assert self.msg.priority == 4, (self.msg.priority)
+    self.msg.ttl = 0.003 # field after priority, so forces priority to be present
+    data = self.msg.encode()
+
+    decoder = Data()
+    decoder.decode(data)
+
+    dheaders = decoder.get_py_described()
+    # Check we've got the correct described list
+    assert dheaders.descriptor == 0x70, (dheaders.descriptor)
+
+    # Check that the priority field (second field) is encoded as null
+    headers = dheaders.value
+    assert headers[1] == None, (headers[1])
+
+  def testDefaultPriorityDecode(self):
+    # This is a message with everything filled explicitly as null or zero in LIST32 HEADER and PROPERTIES lists
+    data = b'\x00\x53\x70\xd0\x00\x00\x00\x0a\x00\x00\x00\x05\x42\x40\x40\x42\x52\x00\x00\x53\x73\xd0\x00\x00\x00\x22\x00\x00\x00\x0d\x40\x40\x40\x40\x40\x40\x40\x40\x83\x00\x00\x00\x00\x00\x00\x00\x00\x83\x00\x00\x00\x00\x00\x00\x00\x00\x40\x52\x00\x40'
+    msg2 = Message()
+    msg2.decode(data)
+    assert msg2.priority == 4, (msg2.priority)
+
+    # The same message with LIST8s instead
+    data = b'\x00\x53\x70\xc0\x07\x05\x42\x40\x40\x42\x52\x00\x00\x53\x73\xc0\x1f\x0d\x40\x40\x40\x40\x40\x40\x40\x40\x83\x00\x00\x00\x00\x00\x00\x00\x00\x83\x00\x00\x00\x00\x00\x00\x00\x00\x40\x52\x00\x40'
+    msg3 = Message()
+    msg3.decode(data)
+    assert msg3.priority == 4, (msg3.priority)
+
+    # Minified message with zero length HEADER and PROPERTIES lists
+    data = b'\x00\x53\x70\x45' b'\x00\x53\x73\x45'
+    msg4 = Message()
+    msg4.decode(data)
+    assert msg4.priority == 4, (msg4.priority)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/reactor.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/reactor.py b/python/tests/proton_tests/reactor.py
new file mode 100644
index 0000000..208baa2
--- /dev/null
+++ b/python/tests/proton_tests/reactor.py
@@ -0,0 +1,485 @@
+from __future__ import absolute_import
+#
+# 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.
+#
+
+import time
+import sys
+from .common import Test, SkipTest, TestServer, free_tcp_port, ensureCanTestExtendedSASL
+from proton.reactor import Container, Reactor, ApplicationEvent, EventInjector
+from proton.handlers import Handshaker, MessagingHandler
+from proton import Handler, Url
+
+class Barf(Exception):
+    pass
+
+class BarfOnInit:
+
+    def on_reactor_init(self, event):
+        raise Barf()
+
+    def on_connection_init(self, event):
+        raise Barf()
+
+    def on_session_init(self, event):
+        raise Barf()
+
+    def on_link_init(self, event):
+        raise Barf()
+
+class BarfOnTask:
+
+    def on_timer_task(self, event):
+        raise Barf()
+
+class BarfOnFinal:
+    init = False
+
+    def on_reactor_init(self, event):
+        self.init = True
+
+    def on_reactor_final(self, event):
+        raise Barf()
+
+class BarfOnFinalDerived(Handshaker):
+    init = False
+
+    def on_reactor_init(self, event):
+        self.init = True
+
+    def on_reactor_final(self, event):
+        raise Barf()
+
+class ExceptionTest(Test):
+
+    def setUp(self):
+        self.reactor = Reactor()
+
+    def test_reactor_final(self):
+        self.reactor.global_handler = BarfOnFinal()
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_global_set(self):
+        self.reactor.global_handler = BarfOnInit()
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_global_add(self):
+        self.reactor.global_handler.add(BarfOnInit())
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_reactor_set(self):
+        self.reactor.handler = BarfOnInit()
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_reactor_add(self):
+        self.reactor.handler.add(BarfOnInit())
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_connection(self):
+        self.reactor.connection(BarfOnInit())
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_connection_set(self):
+        c = self.reactor.connection()
+        c.handler = BarfOnInit()
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_connection_add(self):
+        c = self.reactor.connection()
+        c.handler = object()
+        c.handler.add(BarfOnInit())
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_session_set(self):
+        c = self.reactor.connection()
+        s = c.session()
+        s.handler = BarfOnInit()
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_session_add(self):
+        c = self.reactor.connection()
+        s = c.session()
+        s.handler = object()
+        s.handler.add(BarfOnInit())
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_link_set(self):
+        c = self.reactor.connection()
+        s = c.session()
+        l = s.sender("xxx")
+        l.handler = BarfOnInit()
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_link_add(self):
+        c = self.reactor.connection()
+        s = c.session()
+        l = s.sender("xxx")
+        l.handler = object()
+        l.handler.add(BarfOnInit())
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_schedule(self):
+        self.reactor.schedule(0, BarfOnTask())
+        try:
+            self.reactor.run()
+            assert False, "expected to barf"
+        except Barf:
+            pass
+
+    def test_schedule_many_nothings(self):
+        class Nothing:
+            results = []
+            def on_timer_task(self, event):
+                self.results.append(None)
+        num = 12345
+        for a in range(num):
+            self.reactor.schedule(0, Nothing())
+        self.reactor.run()
+        assert len(Nothing.results) == num
+
+    def test_schedule_many_nothing_refs(self):
+        class Nothing:
+            results = []
+            def on_timer_task(self, event):
+                self.results.append(None)
+        num = 12345
+        tasks = []
+        for a in range(num):
+            tasks.append(self.reactor.schedule(0, Nothing()))
+        self.reactor.run()
+        assert len(Nothing.results) == num
+
+    def test_schedule_many_nothing_refs_cancel_before_run(self):
+        class Nothing:
+            results = []
+            def on_timer_task(self, event):
+                self.results.append(None)
+        num = 12345
+        tasks = []
+        for a in range(num):
+            tasks.append(self.reactor.schedule(0, Nothing()))
+        for task in tasks:
+            task.cancel()
+        self.reactor.run()
+        assert len(Nothing.results) == 0
+
+    def test_schedule_cancel(self):
+        barf = self.reactor.schedule(10, BarfOnTask())
+        class CancelBarf:
+            def __init__(self, barf):
+                self.barf = barf
+            def on_timer_task(self, event):
+                self.barf.cancel()
+                pass
+        self.reactor.schedule(0, CancelBarf(barf))
+        now = self.reactor.mark()
+        try:
+            self.reactor.run()
+            elapsed = self.reactor.mark() - now
+            assert elapsed < 10, "expected cancelled task to not delay the reactor by %s" % elapsed
+        except Barf:
+            assert False, "expected barf to be cancelled"
+
+    def test_schedule_cancel_many(self):
+        num = 12345
+        barfs = set()
+        for a in range(num):
+            barf = self.reactor.schedule(10*(a+1), BarfOnTask())
+            class CancelBarf:
+                def __init__(self, barf):
+                    self.barf = barf
+                def on_timer_task(self, event):
+                    self.barf.cancel()
+                    barfs.discard(self.barf)
+                    pass
+            self.reactor.schedule(0, CancelBarf(barf))
+            barfs.add(barf)
+        now = self.reactor.mark()
+        try:
+            self.reactor.run()
+            elapsed = self.reactor.mark() - now
+            assert elapsed < num, "expected cancelled task to not delay the reactor by %s" % elapsed
+            assert not barfs, "expected all barfs to be discarded"
+        except Barf:
+            assert False, "expected barf to be cancelled"
+
+
+class ApplicationEventTest(Test):
+    """Test application defined events and handlers."""
+
+    class MyTestServer(TestServer):
+        def __init__(self):
+            super(ApplicationEventTest.MyTestServer, self).__init__()
+
+    class MyHandler(Handler):
+        def __init__(self, test):
+            super(ApplicationEventTest.MyHandler, self).__init__()
+            self._test = test
+
+        def on_hello(self, event):
+            # verify PROTON-1056
+            self._test.hello_rcvd = str(event)
+
+        def on_goodbye(self, event):
+            self._test.goodbye_rcvd = str(event)
+
+    def setUp(self):
+        import os
+        if not hasattr(os, 'pipe'):
+          # KAG: seems like Jython doesn't have an os.pipe() method
+          raise SkipTest()
+        if os.name=="nt":
+          # Correct implementation on Windows is complicated
+          raise SkipTest("PROTON-1071")
+        self.server = ApplicationEventTest.MyTestServer()
+        self.server.reactor.handler.add(ApplicationEventTest.MyHandler(self))
+        self.event_injector = EventInjector()
+        self.hello_event = ApplicationEvent("hello")
+        self.goodbye_event = ApplicationEvent("goodbye")
+        self.server.reactor.selectable(self.event_injector)
+        self.hello_rcvd = None
+        self.goodbye_rcvd = None
+        self.server.start()
+
+    def tearDown(self):
+        self.server.stop()
+
+    def _wait_for(self, predicate, timeout=10.0):
+        deadline = time.time() + timeout
+        while time.time() < deadline:
+            if predicate():
+                break
+            time.sleep(0.1)
+        assert predicate()
+
+    def test_application_events(self):
+        self.event_injector.trigger(self.hello_event)
+        self._wait_for(lambda: self.hello_rcvd is not None)
+        self.event_injector.trigger(self.goodbye_event)
+        self._wait_for(lambda: self.goodbye_rcvd is not None)
+
+
+class AuthenticationTestHandler(MessagingHandler):
+    def __init__(self):
+        super(AuthenticationTestHandler, self).__init__()
+        port = free_tcp_port()
+        self.url = "localhost:%i" % port
+        self.verified = False
+
+    def on_start(self, event):
+        self.listener = event.container.listen(self.url)
+
+    def on_connection_opened(self, event):
+        event.connection.close()
+
+    def on_connection_opening(self, event):
+        assert event.connection.transport.user == "user@proton"
+        self.verified = True
+
+    def on_connection_closed(self, event):
+        event.connection.close()
+        self.listener.close()
+
+    def on_connection_error(self, event):
+        event.connection.close()
+        self.listener.close()
+
+class ContainerTest(Test):
+    """Test container subclass of reactor."""
+
+    def test_event_has_container_attribute(self):
+        ensureCanTestExtendedSASL()
+        class TestHandler(MessagingHandler):
+            def __init__(self):
+                super(TestHandler, self).__init__()
+                port = free_tcp_port()
+                self.url = "localhost:%i" % port
+
+            def on_start(self, event):
+                self.listener = event.container.listen(self.url)
+
+            def on_connection_closing(self, event):
+                event.connection.close()
+                self.listener.close()
+        test_handler = TestHandler()
+        container = Container(test_handler)
+        class ConnectionHandler(MessagingHandler):
+            def __init__(self):
+                super(ConnectionHandler, self).__init__()
+
+            def on_connection_opened(self, event):
+                event.connection.close()
+                assert event.container == event.reactor
+                assert event.container == container
+        container.connect(test_handler.url, handler=ConnectionHandler())
+        container.run()
+
+    def test_authentication_via_url(self):
+        ensureCanTestExtendedSASL()
+        test_handler = AuthenticationTestHandler()
+        container = Container(test_handler)
+        container.connect("%s:password@%s" % ("user%40proton", test_handler.url), reconnect=False)
+        container.run()
+        assert test_handler.verified
+
+    def test_authentication_via_container_attributes(self):
+        ensureCanTestExtendedSASL()
+        test_handler = AuthenticationTestHandler()
+        container = Container(test_handler)
+        container.user = "user@proton"
+        container.password = "password"
+        container.connect(test_handler.url, reconnect=False)
+        container.run()
+        assert test_handler.verified
+
+    def test_authentication_via_kwargs(self):
+        ensureCanTestExtendedSASL()
+        test_handler = AuthenticationTestHandler()
+        container = Container(test_handler)
+        container.connect(test_handler.url, user="user@proton", password="password", reconnect=False)
+        container.run()
+        assert test_handler.verified
+
+    class _ServerHandler(MessagingHandler):
+        def __init__(self, host):
+            super(ContainerTest._ServerHandler, self).__init__()
+            self.host = host
+            port = free_tcp_port()
+            self.port = free_tcp_port()
+            self.client_addr = None
+            self.peer_hostname = None
+
+        def on_start(self, event):
+            self.listener = event.container.listen("%s:%s" % (self.host, self.port))
+
+        def on_connection_opened(self, event):
+            self.client_addr = event.reactor.get_connection_address(event.connection)
+            self.peer_hostname = event.connection.remote_hostname
+
+        def on_connection_closing(self, event):
+            event.connection.close()
+            self.listener.close()
+
+    class _ClientHandler(MessagingHandler):
+        def __init__(self):
+            super(ContainerTest._ClientHandler, self).__init__()
+            self.server_addr = None
+
+        def on_connection_opened(self, event):
+            self.server_addr = event.reactor.get_connection_address(event.connection)
+            event.connection.close()
+
+    def test_numeric_hostname(self):
+        ensureCanTestExtendedSASL()
+        server_handler = ContainerTest._ServerHandler("127.0.0.1")
+        client_handler = ContainerTest._ClientHandler()
+        container = Container(server_handler)
+        container.connect(url=Url(host="127.0.0.1",
+                                  port=server_handler.port),
+                          handler=client_handler)
+        container.run()
+        assert server_handler.client_addr
+        assert client_handler.server_addr
+        assert server_handler.peer_hostname == "127.0.0.1", server_handler.peer_hostname
+        assert client_handler.server_addr.rsplit(':', 1)[1] == str(server_handler.port)
+
+    def test_non_numeric_hostname(self):
+        ensureCanTestExtendedSASL()
+        server_handler = ContainerTest._ServerHandler("localhost")
+        client_handler = ContainerTest._ClientHandler()
+        container = Container(server_handler)
+        container.connect(url=Url(host="localhost",
+                                  port=server_handler.port),
+                          handler=client_handler)
+        container.run()
+        assert server_handler.client_addr
+        assert client_handler.server_addr
+        assert server_handler.peer_hostname == "localhost", server_handler.peer_hostname
+        assert client_handler.server_addr.rsplit(':', 1)[1] == str(server_handler.port)
+
+    def test_virtual_host(self):
+        ensureCanTestExtendedSASL()
+        server_handler = ContainerTest._ServerHandler("localhost")
+        container = Container(server_handler)
+        conn = container.connect(url=Url(host="localhost",
+                                         port=server_handler.port),
+                                 handler=ContainerTest._ClientHandler(),
+                                 virtual_host="a.b.c.org")
+        container.run()
+        assert server_handler.peer_hostname == "a.b.c.org", server_handler.peer_hostname
+
+    def test_no_virtual_host(self):
+        # explicitly setting an empty virtual host should prevent the hostname
+        # field from being sent in the Open performative when using the
+        # Python Container.
+        server_handler = ContainerTest._ServerHandler("localhost")
+        container = Container(server_handler)
+        conn = container.connect(url=Url(host="localhost",
+                                         port=server_handler.port),
+                                 handler=ContainerTest._ClientHandler(),
+                                 virtual_host="")
+        container.run()
+        assert server_handler.peer_hostname is None, server_handler.peer_hostname

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/sasl.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/sasl.py b/python/tests/proton_tests/sasl.py
new file mode 100644
index 0000000..09b5f81
--- /dev/null
+++ b/python/tests/proton_tests/sasl.py
@@ -0,0 +1,587 @@
+#
+# 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.
+#
+from __future__ import absolute_import
+
+import sys, os
+from . import common
+from . import engine
+
+from proton import *
+from .common import pump, Skipped
+
+def _sslCertpath(file):
+    """ Return the full path to the certificate, keyfile, etc.
+    """
+    if os.name=="nt":
+        if file.find("private-key")!=-1:
+            # The private key is not in a separate store
+            return None
+        # Substitute pkcs#12 equivalent for the CA/key store
+        if file.endswith(".pem"):
+            file = file[:-4] + ".p12"
+    return os.path.join(os.path.dirname(__file__),
+                        "ssl_db/%s" % file)
+
+def _testSaslMech(self, mech, clientUser='user@proton', authUser='user@proton', encrypted=False, authenticated=True):
+  self.s1.allowed_mechs(mech)
+  self.c1.open()
+  self.c2.open()
+
+  pump(self.t1, self.t2, 1024)
+
+  if encrypted is not None:
+    assert self.t2.encrypted == encrypted, encrypted
+    assert self.t1.encrypted == encrypted, encrypted
+
+  assert self.t2.authenticated == authenticated, authenticated
+  assert self.t1.authenticated == authenticated, authenticated
+  if authenticated:
+    # Server
+    assert self.t2.user == authUser
+    assert self.s2.user == authUser
+    assert self.s2.mech == mech.strip()
+    assert self.s2.outcome == SASL.OK, self.s2.outcome
+    assert self.c2.state & Endpoint.LOCAL_ACTIVE and self.c2.state & Endpoint.REMOTE_ACTIVE,\
+      "local_active=%s, remote_active=%s" % (self.c1.state & Endpoint.LOCAL_ACTIVE, self.c1.state & Endpoint.REMOTE_ACTIVE)
+    # Client
+    assert self.t1.user == clientUser
+    assert self.s1.user == clientUser
+    assert self.s1.mech == mech.strip()
+    assert self.s1.outcome == SASL.OK, self.s1.outcome
+    assert self.c1.state & Endpoint.LOCAL_ACTIVE and self.c1.state & Endpoint.REMOTE_ACTIVE,\
+      "local_active=%s, remote_active=%s" % (self.c1.state & Endpoint.LOCAL_ACTIVE, self.c1.state & Endpoint.REMOTE_ACTIVE)
+  else:
+    # Server
+    assert self.t2.user == None
+    assert self.s2.user == None
+    assert self.s2.outcome != SASL.OK, self.s2.outcome
+    # Client
+    assert self.t1.user == clientUser
+    assert self.s1.user == clientUser
+    assert self.s1.outcome != SASL.OK, self.s1.outcome
+
+class Test(common.Test):
+  pass
+
+def consumeAllOuput(t):
+  stops = 0
+  while stops<1:
+    out = t.peek(1024)
+    l = len(out) if out else 0
+    t.pop(l)
+    if l <= 0:
+      stops += 1
+
+class SaslTest(Test):
+
+  def setUp(self):
+    self.t1 = Transport()
+    self.s1 = SASL(self.t1)
+    self.t2 = Transport(Transport.SERVER)
+    self.t2.max_frame_size = 65536
+    self.s2 = SASL(self.t2)
+
+  def pump(self):
+    pump(self.t1, self.t2, 1024)
+
+  # We have to generate the client frames manually because proton does not
+  # generate pipelined SASL and AMQP frames together
+  def testIllegalProtocolLayering(self):
+    # Server
+    self.s2.allowed_mechs('ANONYMOUS')
+
+    c2 = Connection()
+    self.t2.bind(c2)
+
+    assert self.s2.outcome is None
+
+    # Push client bytes into server
+    self.t2.push(
+        # SASL
+        b'AMQP\x03\x01\x00\x00'
+        # @sasl-init(65) [mechanism=:ANONYMOUS, initial-response=b"anonymous@fuschia"]
+        b'\x00\x00\x002\x02\x01\x00\x00\x00SA\xd0\x00\x00\x00"\x00\x00\x00\x02\xa3\x09ANONYMOUS\xa0\x11anonymous@fuschia'
+        # SASL (again illegally)
+        b'AMQP\x03\x01\x00\x00'
+        # @sasl-init(65) [mechanism=:ANONYMOUS, initial-response=b"anonymous@fuschia"]
+        b'\x00\x00\x002\x02\x01\x00\x00\x00SA\xd0\x00\x00\x00"\x00\x00\x00\x02\xa3\x09ANONYMOUS\xa0\x11anonymous@fuschia'
+        # AMQP
+        b'AMQP\x00\x01\x00\x00'
+        # @open(16) [container-id="", channel-max=1234]
+        b'\x00\x00\x00!\x02\x00\x00\x00\x00S\x10\xd0\x00\x00\x00\x11\x00\x00\x00\x0a\xa1\x00@@`\x04\xd2@@@@@@'
+        )
+
+    consumeAllOuput(self.t2)
+
+    assert self.t2.condition
+    assert self.t2.closed
+    assert not c2.state & Endpoint.REMOTE_ACTIVE
+
+  def testPipelinedClient(self):
+    # Server
+    self.s2.allowed_mechs('ANONYMOUS')
+
+    c2 = Connection()
+    self.t2.bind(c2)
+
+    assert self.s2.outcome is None
+
+    # Push client bytes into server
+    self.t2.push(
+        # SASL
+        b'AMQP\x03\x01\x00\x00'
+        # @sasl-init(65) [mechanism=:ANONYMOUS, initial-response=b"anonymous@fuschia"]
+        b'\x00\x00\x002\x02\x01\x00\x00\x00SA\xd0\x00\x00\x00"\x00\x00\x00\x02\xa3\x09ANONYMOUS\xa0\x11anonymous@fuschia'
+        # AMQP
+        b'AMQP\x00\x01\x00\x00'
+        # @open(16) [container-id="", channel-max=1234]
+        b'\x00\x00\x00!\x02\x00\x00\x00\x00S\x10\xd0\x00\x00\x00\x11\x00\x00\x00\x0a\xa1\x00@@`\x04\xd2@@@@@@'
+        )
+
+    consumeAllOuput(self.t2)
+
+    assert not self.t2.condition
+    assert self.s2.outcome == SASL.OK
+    assert c2.state & Endpoint.REMOTE_ACTIVE
+
+  def testPipelinedServer(self):
+    # Client
+    self.s1.allowed_mechs('ANONYMOUS')
+
+    c1 = Connection()
+    self.t1.bind(c1)
+
+    assert self.s1.outcome is None
+
+    # Push server bytes into client
+    # Commented out lines in this test are where the client input processing doesn't
+    # run after output processing even though there is input waiting
+    self.t1.push(
+        # SASL
+        b'AMQP\x03\x01\x00\x00'
+        # @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:ANONYMOUS]]
+        b'\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS'
+        # @sasl-outcome(68) [code=0]
+        b'\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00'
+        # AMQP
+        b'AMQP\x00\x01\x00\x00'
+        # @open(16) [container-id="", channel-max=1234]
+        b'\x00\x00\x00!\x02\x00\x00\x00\x00S\x10\xd0\x00\x00\x00\x11\x00\x00\x00\x0a\xa1\x00@@`\x04\xd2@@@@@@'
+        )
+
+    consumeAllOuput(self.t1)
+
+    assert self.s1.outcome == SASL.OK
+    assert c1.state & Endpoint.REMOTE_ACTIVE
+
+  def testPipelined2(self):
+    out1 = self.t1.peek(1024)
+    self.t1.pop(len(out1))
+    self.t2.push(out1)
+
+    self.s2.allowed_mechs('ANONYMOUS')
+    c2 = Connection()
+    c2.open()
+    self.t2.bind(c2)
+
+    out2 = self.t2.peek(1024)
+    self.t2.pop(len(out2))
+    self.t1.push(out2)
+
+    out1 = self.t1.peek(1024)
+    assert len(out1) > 0
+
+  def testFracturedSASL(self):
+    """ PROTON-235
+    """
+    assert self.s1.outcome is None
+
+    # self.t1.trace(Transport.TRACE_FRM)
+
+    out = self.t1.peek(1024)
+    self.t1.pop(len(out))
+    self.t1.push(b"AMQP\x03\x01\x00\x00")
+    out = self.t1.peek(1024)
+    self.t1.pop(len(out))
+    self.t1.push(b"\x00\x00\x00")
+    out = self.t1.peek(1024)
+    self.t1.pop(len(out))
+
+    self.t1.push(b"6\x02\x01\x00\x00\x00S@\xc0\x29\x01\xe0\x26\x04\xa3\x05PLAIN\x0aDIGEST-MD5\x09ANONYMOUS\x08CRAM-MD5")
+    out = self.t1.peek(1024)
+    self.t1.pop(len(out))
+    self.t1.push(b"\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00")
+    out = self.t1.peek(1024)
+    self.t1.pop(len(out))
+    while out:
+      out = self.t1.peek(1024)
+      self.t1.pop(len(out))
+
+    assert self.s1.outcome == SASL.OK, self.s1.outcome
+
+  def test_singleton(self):
+      """Verify that only a single instance of SASL can exist per Transport"""
+      transport = Transport()
+      attr = object()
+      sasl1 = SASL(transport)
+      sasl1.my_attribute = attr
+      sasl2 = transport.sasl()
+      sasl3 = SASL(transport)
+      assert sasl1 == sasl2
+      assert sasl1 == sasl3
+      assert sasl1.my_attribute == attr
+      assert sasl2.my_attribute == attr
+      assert sasl3.my_attribute == attr
+      transport = Transport()
+      sasl1 = transport.sasl()
+      sasl1.my_attribute = attr
+      sasl2 = SASL(transport)
+      assert sasl1 == sasl2
+      assert sasl1.my_attribute == attr
+      assert sasl2.my_attribute == attr
+
+  def testSaslSkipped(self):
+    """Verify that the server (with SASL) correctly handles a client without SASL"""
+    self.t1 = Transport()
+    self.t2.require_auth(False)
+    self.pump()
+    assert self.s2.outcome == None
+    assert self.t2.condition == None
+    assert self.t2.authenticated == False
+    assert self.s1.outcome == None
+    assert self.t1.condition == None
+    assert self.t1.authenticated == False
+
+  def testSaslSkippedFail(self):
+    """Verify that the server (with SASL) correctly handles a client without SASL"""
+    self.t1 = Transport()
+    self.t2.require_auth(True)
+    self.pump()
+    assert self.s2.outcome == None
+    assert self.t2.condition != None
+    assert self.s1.outcome == None
+    assert self.t1.condition != None
+
+  def testMechNotFound(self):
+    self.c1 = Connection()
+    self.c1.open()
+    self.t1.bind(self.c1)
+    self.s1.allowed_mechs('IMPOSSIBLE')
+
+    self.pump()
+
+    assert self.t2.authenticated == False
+    assert self.t1.authenticated == False
+    assert self.s1.outcome != SASL.OK
+    assert self.s2.outcome != SASL.OK
+
+class SASLMechTest(Test):
+  def setUp(self):
+    self.t1 = Transport()
+    self.s1 = SASL(self.t1)
+    self.t2 = Transport(Transport.SERVER)
+    self.s2 = SASL(self.t2)
+
+    self.c1 = Connection()
+    self.c1.user = 'user@proton'
+    self.c1.password = 'password'
+    self.c1.hostname = 'localhost'
+
+    self.c2 = Connection()
+
+  def testANON(self):
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'ANONYMOUS', authUser='anonymous')
+
+  def testCRAMMD5(self):
+    common.ensureCanTestExtendedSASL()
+
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'CRAM-MD5')
+
+  def testDIGESTMD5(self):
+    common.ensureCanTestExtendedSASL()
+
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'DIGEST-MD5')
+
+  # PLAIN shouldn't work without encryption without special setting
+  def testPLAINfail(self):
+    common.ensureCanTestExtendedSASL()
+
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'PLAIN', authenticated=False)
+
+  # Client won't accept PLAIN even if offered by server without special setting
+  def testPLAINClientFail(self):
+    common.ensureCanTestExtendedSASL()
+
+    self.s2.allow_insecure_mechs = True
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'PLAIN', authenticated=False)
+
+  # PLAIN will only work if both ends are specially set up
+  def testPLAIN(self):
+    common.ensureCanTestExtendedSASL()
+
+    self.s1.allow_insecure_mechs = True
+    self.s2.allow_insecure_mechs = True
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'PLAIN')
+
+# SCRAM not supported before Cyrus SASL 2.1.26
+# so not universal and hence need a test for support
+# to keep it in tests.
+#  def testSCRAMSHA1(self):
+#    common.ensureCanTestExtendedSASL()
+#
+#    self.t1.bind(self.c1)
+#    self.t2.bind(self.c2)
+#    _testSaslMech(self, 'SCRAM-SHA-1')
+
+def _sslConnection(domain, transport, connection):
+  transport.bind(connection)
+  ssl = SSL(transport, domain, None )
+  return connection
+
+class SSLSASLTest(Test):
+  def setUp(self):
+    if not common.isSSLPresent():
+      raise Skipped("No SSL libraries found.")
+
+    self.server_domain = SSLDomain(SSLDomain.MODE_SERVER)
+    self.client_domain = SSLDomain(SSLDomain.MODE_CLIENT)
+
+    self.t1 = Transport()
+    self.s1 = SASL(self.t1)
+    self.t2 = Transport(Transport.SERVER)
+    self.s2 = SASL(self.t2)
+
+    self.c1 = Connection()
+    self.c2 = Connection()
+
+  def testSSLPlainSimple(self):
+    if not SASL.extended():
+      raise Skipped("Simple SASL server does not support PLAIN")
+    common.ensureCanTestExtendedSASL()
+
+    clientUser = 'user@proton'
+    mech = 'PLAIN'
+
+    self.c1.user = clientUser
+    self.c1.password = 'password'
+    self.c1.hostname = 'localhost'
+
+    ssl1 = _sslConnection(self.client_domain, self.t1, self.c1)
+    ssl2 = _sslConnection(self.server_domain, self.t2, self.c2)
+
+    _testSaslMech(self, mech, encrypted=True)
+
+  def testSSLPlainSimpleFail(self):
+    if not SASL.extended():
+      raise Skipped("Simple SASL server does not support PLAIN")
+    common.ensureCanTestExtendedSASL()
+
+    clientUser = 'usr@proton'
+    mech = 'PLAIN'
+
+    self.c1.user = clientUser
+    self.c1.password = 'password'
+    self.c1.hostname = 'localhost'
+
+    ssl1 = _sslConnection(self.client_domain, self.t1, self.c1)
+    ssl2 = _sslConnection(self.server_domain, self.t2, self.c2)
+
+    _testSaslMech(self, mech, clientUser='usr@proton', encrypted=True, authenticated=False)
+
+  def testSSLExternalSimple(self):
+    if os.name=="nt":
+      extUser = 'O=Client, CN=127.0.0.1'
+    else:
+      extUser = 'O=Client,CN=127.0.0.1'
+    mech = 'EXTERNAL'
+
+    self.server_domain.set_credentials(_sslCertpath("server-certificate.pem"),
+                                       _sslCertpath("server-private-key.pem"),
+                                       "server-password")
+    self.server_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem"))
+    self.server_domain.set_peer_authentication(SSLDomain.VERIFY_PEER,
+                                               _sslCertpath("ca-certificate.pem") )
+    self.client_domain.set_credentials(_sslCertpath("client-certificate.pem"),
+                                       _sslCertpath("client-private-key.pem"),
+                                       "client-password")
+    self.client_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem"))
+    self.client_domain.set_peer_authentication(SSLDomain.VERIFY_PEER)
+
+    ssl1 = _sslConnection(self.client_domain, self.t1, self.c1)
+    ssl2 = _sslConnection(self.server_domain, self.t2, self.c2)
+
+    _testSaslMech(self, mech, clientUser=None, authUser=extUser, encrypted=True)
+
+  def testSSLExternalSimpleFail(self):
+    mech = 'EXTERNAL'
+
+    self.server_domain.set_credentials(_sslCertpath("server-certificate.pem"),
+                                       _sslCertpath("server-private-key.pem"),
+                                       "server-password")
+    self.server_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem"))
+    self.server_domain.set_peer_authentication(SSLDomain.VERIFY_PEER,
+                                               _sslCertpath("ca-certificate.pem") )
+    self.client_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem"))
+    self.client_domain.set_peer_authentication(SSLDomain.VERIFY_PEER)
+
+    ssl1 = _sslConnection(self.client_domain, self.t1, self.c1)
+    ssl2 = _sslConnection(self.server_domain, self.t2, self.c2)
+
+    _testSaslMech(self, mech, clientUser=None, authUser=None, encrypted=None, authenticated=False)
+
+class SASLEventTest(engine.CollectorTest):
+  def setUp(self):
+    engine.CollectorTest.setUp(self)
+    self.t1 = Transport()
+    self.s1 = SASL(self.t1)
+    self.t2 = Transport(Transport.SERVER)
+    self.s2 = SASL(self.t2)
+
+    self.c1 = Connection()
+    self.c1.user = 'user@proton'
+    self.c1.password = 'password'
+    self.c1.hostname = 'localhost'
+
+    self.c2 = Connection()
+
+    self.collector = Collector()
+
+  def testNormalAuthenticationClient(self):
+    common.ensureCanTestExtendedSASL()
+    self.c1.collect(self.collector)
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'DIGEST-MD5')
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.CONNECTION_REMOTE_OPEN)
+
+  def testNormalAuthenticationServer(self):
+    common.ensureCanTestExtendedSASL()
+    self.c2.collect(self.collector)
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'DIGEST-MD5')
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.CONNECTION_REMOTE_OPEN)
+
+  def testFailedAuthenticationClient(self):
+    common.ensureCanTestExtendedSASL()
+    clientUser = "usr@proton"
+    self.c1.user = clientUser
+    self.c1.collect(self.collector)
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'DIGEST-MD5', clientUser=clientUser, authenticated=False)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.TRANSPORT_ERROR,
+                Event.TRANSPORT_TAIL_CLOSED,
+                Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+  def testFailedAuthenticationServer(self):
+    common.ensureCanTestExtendedSASL()
+    clientUser = "usr@proton"
+    self.c1.user = clientUser
+    self.c2.collect(self.collector)
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'DIGEST-MD5', clientUser=clientUser, authenticated=False)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.TRANSPORT_ERROR,
+                Event.TRANSPORT_TAIL_CLOSED,
+                Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+  def testNoMechClient(self):
+    common.ensureCanTestExtendedSASL()
+    self.c1.collect(self.collector)
+    self.s2.allowed_mechs('IMPOSSIBLE')
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'DIGEST-MD5', authenticated=False)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.TRANSPORT_ERROR,
+                Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+  def testNoMechServer(self):
+    common.ensureCanTestExtendedSASL()
+    self.c2.collect(self.collector)
+    self.s2.allowed_mechs('IMPOSSIBLE')
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'DIGEST-MD5', authenticated=False)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.TRANSPORT_TAIL_CLOSED,
+                Event.TRANSPORT_ERROR, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+  def testDisallowedMechClient(self):
+    self.c1.collect(self.collector)
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'IMPOSSIBLE', authenticated=False)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.TRANSPORT_ERROR,
+                Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+  def testDisallowedMechServer(self):
+    self.c2.collect(self.collector)
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'IMPOSSIBLE', authenticated=False)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.TRANSPORT_TAIL_CLOSED,
+                Event.TRANSPORT_ERROR, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+  def testDisallowedPlainClient(self):
+    self.c1.collect(self.collector)
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'PLAIN', authenticated=False)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.TRANSPORT_ERROR,
+                Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+  def testDisallowedPlainServer(self):
+    self.c2.collect(self.collector)
+    self.t1.bind(self.c1)
+    self.t2.bind(self.c2)
+    _testSaslMech(self, 'PLAIN', authenticated=False)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.TRANSPORT_TAIL_CLOSED,
+                Event.TRANSPORT_ERROR, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/soak.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/soak.py b/python/tests/proton_tests/soak.py
new file mode 100644
index 0000000..b7b521c
--- /dev/null
+++ b/python/tests/proton_tests/soak.py
@@ -0,0 +1,334 @@
+from __future__ import absolute_import
+#
+# 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.
+#
+import os
+import sys
+from .common import Test, Skipped, free_tcp_ports, \
+    MessengerReceiverC, MessengerSenderC, \
+    MessengerReceiverValgrind, MessengerSenderValgrind, \
+    ReactorReceiverC, ReactorSenderC, \
+    ReactorReceiverValgrind, ReactorSenderValgrind, \
+    isSSLPresent
+from proton import *
+
+#
+# Tests that run the apps
+#
+
+class AppTests(Test):
+
+    def __init__(self, *args):
+        Test.__init__(self, *args)
+        self.is_valgrind = False
+
+    def default(self, name, value, **kwargs):
+        if self.is_valgrind:
+            default = kwargs.get("valgrind", value)
+        else:
+            default = value
+        return Test.default(self, name, default, **kwargs)
+
+    @property
+    def iterations(self):
+        return int(self.default("iterations", 2, fast=1, valgrind=2))
+
+    @property
+    def send_count(self):
+        return int(self.default("send_count", 17, fast=1, valgrind=2))
+
+    @property
+    def target_count(self):
+        return int(self.default("target_count", 5, fast=1, valgrind=2))
+
+    @property
+    def send_batch(self):
+        return int(self.default("send_batch", 7, fast=1, valgrind=2))
+
+    @property
+    def forward_count(self):
+        return int(self.default("forward_count", 5, fast=1, valgrind=2))
+
+    @property
+    def port_count(self):
+        return int(self.default("port_count", 3, fast=1, valgrind=2))
+
+    @property
+    def sender_count(self):
+        return int(self.default("sender_count", 3, fast=1, valgrind=2))
+
+    def valgrind_test(self):
+        self.is_valgrind = True
+
+    def setUp(self):
+        self.senders = []
+        self.receivers = []
+
+    def tearDown(self):
+        pass
+
+    def _do_test(self, iterations=1):
+        verbose = self.verbose
+
+        for R in self.receivers:
+            R.start( verbose )
+
+        for j in range(iterations):
+            for S in self.senders:
+                S.start( verbose )
+
+            for S in self.senders:
+                S.wait()
+                #print("SENDER OUTPUT:")
+                #print( S.stdout() )
+                assert S.status() == 0, ("Command '%s' failed status=%d: '%s' '%s'"
+                                         % (str(S.cmdline()),
+                                            S.status(),
+                                            S.stdout(),
+                                            S.stderr()))
+
+        for R in self.receivers:
+            R.wait()
+            #print("RECEIVER OUTPUT")
+            #print( R.stdout() )
+            assert R.status() == 0, ("Command '%s' failed status=%d: '%s' '%s'"
+                                     % (str(R.cmdline()),
+                                        R.status(),
+                                        R.stdout(),
+                                        R.stderr()))
+
+#
+# Traffic passing tests based on the Messenger apps
+#
+
+class MessengerTests(AppTests):
+
+    _timeout = 60
+
+    def _ssl_check(self):
+        if not isSSLPresent():
+            raise Skipped("No SSL libraries found.")
+        if os.name=="nt":
+            raise Skipped("Windows SChannel lacks anonymous cipher support.")
+
+    def __init__(self, *args):
+        AppTests.__init__(self, *args)
+
+    def _do_oneway_test(self, receiver, sender, domain="amqp"):
+        """ Send N messages to a receiver.
+        Parameters:
+        iterations - repeat the senders this many times
+        target_count = # of targets to send to.
+        send_count = # messages sent to each target
+        """
+        iterations = self.iterations
+        send_count = self.send_count
+        target_count = self.target_count
+
+        send_total = send_count * target_count
+        receive_total = send_total * iterations
+
+        port = free_tcp_ports()[0]
+
+        receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port)]
+        receiver.receive_count = receive_total
+        receiver.timeout = MessengerTests._timeout
+        self.receivers.append( receiver )
+
+        sender.targets = ["%s://0.0.0.0:%s/X%d" % (domain, port, j) for j in range(target_count)]
+        sender.send_count = send_total
+        sender.timeout = MessengerTests._timeout
+        self.senders.append( sender )
+
+        self._do_test(iterations)
+
+    def _do_echo_test(self, receiver, sender, domain="amqp"):
+        """ Send N messages to a receiver, which responds to each.
+        Parameters:
+        iterations - repeat the senders this many times
+        target_count - # targets to send to
+        send_count = # messages sent to each target
+        send_batch - wait for replies after this many messages sent
+        """
+        iterations = self.iterations
+        send_count = self.send_count
+        target_count = self.target_count
+        send_batch = self.send_batch
+
+        send_total = send_count * target_count
+        receive_total = send_total * iterations
+
+        port = free_tcp_ports()[0]
+
+        receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port)]
+        receiver.receive_count = receive_total
+        receiver.send_reply = True
+        receiver.timeout = MessengerTests._timeout
+        self.receivers.append( receiver )
+
+        sender.targets = ["%s://0.0.0.0:%s/%dY" % (domain, port, j) for j in range(target_count)]
+        sender.send_count = send_total
+        sender.get_reply = True
+        sender.send_batch = send_batch
+        sender.timeout = MessengerTests._timeout
+        self.senders.append( sender )
+
+        self._do_test(iterations)
+
+    def _do_relay_test(self, receiver, relay, sender, domain="amqp"):
+        """ Send N messages to a receiver, which replies to each and forwards
+        each of them to different receiver.
+        Parameters:
+        iterations - repeat the senders this many times
+        target_count - # targets to send to
+        send_count = # messages sent to each target
+        send_batch - wait for replies after this many messages sent
+        forward_count - forward to this many targets
+        """
+        iterations = self.iterations
+        send_count = self.send_count
+        target_count = self.target_count
+        send_batch = self.send_batch
+        forward_count = self.forward_count
+
+        send_total = send_count * target_count
+        receive_total = send_total * iterations
+
+        port = free_tcp_ports()[0]
+
+        receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port)]
+        receiver.receive_count = receive_total
+        receiver.send_reply = True
+        # forward to 'relay' - uses two links
+        # ## THIS FAILS:
+        # receiver.forwards = ["amqp://Relay/%d" % j for j in range(forward_count)]
+        receiver.forwards = ["%s://Relay" % domain]
+        receiver.timeout = MessengerTests._timeout
+        self.receivers.append( receiver )
+
+        relay.subscriptions = ["%s://0.0.0.0:%s" % (domain, port)]
+        relay.name = "Relay"
+        relay.receive_count = receive_total
+        relay.timeout = MessengerTests._timeout
+        self.receivers.append( relay )
+
+        # send to 'receiver'
+        sender.targets = ["%s://0.0.0.0:%s/X%dY" % (domain, port, j) for j in range(target_count)]
+        sender.send_count = send_total
+        sender.get_reply = True
+        sender.timeout = MessengerTests._timeout
+        self.senders.append( sender )
+
+        self._do_test(iterations)
+
+
+    def _do_star_topology_test(self, r_factory, s_factory, domain="amqp"):
+        """
+        A star-like topology, with a central receiver at the hub, and senders at
+        the spokes.  Each sender will connect to each of the ports the receiver is
+        listening on.  Each sender will then create N links per each connection.
+        Each sender will send X messages per link, waiting for a response.
+        Parameters:
+        iterations - repeat the senders this many times
+        port_count - # of ports the receiver will listen on.  Each sender connects
+                     to all ports.
+        sender_count - # of senders
+        target_count - # of targets per connection
+        send_count - # of messages sent to each target
+        send_batch - # of messages to send before waiting for response
+        """
+        iterations = self.iterations
+        port_count = self.port_count
+        sender_count = self.sender_count
+        target_count = self.target_count
+        send_count = self.send_count
+        send_batch = self.send_batch
+
+        send_total = port_count * target_count * send_count
+        receive_total = send_total * sender_count * iterations
+
+        ports = free_tcp_ports(port_count)
+
+        receiver = r_factory()
+        receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port) for port in ports]
+        receiver.receive_count = receive_total
+        receiver.send_reply = True
+        receiver.timeout = MessengerTests._timeout
+        self.receivers.append( receiver )
+
+        for i in range(sender_count):
+            sender = s_factory()
+            sender.targets = ["%s://0.0.0.0:%s/%d" % (domain, port, j) for port in ports for j in range(target_count)]
+            sender.send_count = send_total
+            sender.send_batch = send_batch
+            sender.get_reply = True
+            sender.timeout = MessengerTests._timeout
+            self.senders.append( sender )
+
+        self._do_test(iterations)
+
+    def test_oneway_C(self):
+        self._do_oneway_test(MessengerReceiverC(), MessengerSenderC())
+
+    def test_oneway_C_SSL(self):
+        self._ssl_check()
+        self._do_oneway_test(MessengerReceiverC(), MessengerSenderC(), "amqps")
+
+    def test_oneway_valgrind(self):
+        self.valgrind_test()
+        self._do_oneway_test(MessengerReceiverValgrind(), MessengerSenderValgrind())
+
+    def test_echo_C(self):
+        self._do_echo_test(MessengerReceiverC(), MessengerSenderC())
+
+    def test_echo_C_SSL(self):
+        self._ssl_check()
+        self._do_echo_test(MessengerReceiverC(), MessengerSenderC(), "amqps")
+
+    def test_echo_valgrind(self):
+        self.valgrind_test()
+        self._do_echo_test(MessengerReceiverValgrind(), MessengerSenderValgrind())
+
+    def test_relay_C(self):
+        self._do_relay_test(MessengerReceiverC(), MessengerReceiverC(), MessengerSenderC())
+
+    def test_relay_C_SSL(self):
+        self._ssl_check()
+        self._do_relay_test(MessengerReceiverC(), MessengerReceiverC(), MessengerSenderC(), "amqps")
+
+    def test_relay_valgrind(self):
+        self.valgrind_test()
+        self._do_relay_test(MessengerReceiverValgrind(), MessengerReceiverValgrind(), MessengerSenderValgrind())
+
+    def test_star_topology_C(self):
+        self._do_star_topology_test( MessengerReceiverC, MessengerSenderC )
+
+    def test_star_topology_C_SSL(self):
+        self._ssl_check()
+        self._do_star_topology_test( MessengerReceiverC, MessengerSenderC, "amqps" )
+
+    def test_star_topology_valgrind(self):
+        self.valgrind_test()
+        self._do_star_topology_test( MessengerReceiverValgrind, MessengerSenderValgrind )
+
+    def test_oneway_reactor(self):
+        self._do_oneway_test(ReactorReceiverC(), ReactorSenderC())
+
+    def test_oneway_reactor_valgrind(self):
+        self.valgrind_test()
+        self._do_oneway_test(ReactorReceiverValgrind(), ReactorSenderValgrind())


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[06/11] qpid-proton git commit: PROTON-1885: [python] move tests/python to python/tests

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/engine.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/engine.py b/tests/python/proton_tests/engine.py
deleted file mode 100644
index c0ea31d..0000000
--- a/tests/python/proton_tests/engine.py
+++ /dev/null
@@ -1,2714 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-from __future__ import absolute_import
-
-import os, gc
-import sys
-from . import common
-from time import time, sleep
-from proton import *
-from .common import pump, Skipped
-from proton.reactor import Reactor
-
-
-# older versions of gc do not provide the garbage list
-if not hasattr(gc, "garbage"):
-  gc.garbage=[]
-
-# future test areas
-#  + different permutations of setup
-#   - creating deliveries and calling input/output before opening the session/link
-#  + shrinking output_size down to something small? should the engine buffer?
-#  + resuming
-#    - locally and remotely created deliveries with the same tag
-
-# Jython 2.5 needs this:
-try:
-    bytes()
-except:
-    bytes = str
-
-# and this...
-try:
-    bytearray()
-except:
-    def bytearray(x):
-        return b'\x00' * x
-
-OUTPUT_SIZE = 10*1024
-
-class Test(common.Test):
-
-  def __init__(self, *args):
-    common.Test.__init__(self, *args)
-    self._wires = []
-
-  def connection(self):
-    c1 = Connection()
-    c2 = Connection()
-    t1 = Transport()
-    t1.bind(c1)
-    t2 = Transport()
-    t2.bind(c2)
-    self._wires.append((c1, t1, c2, t2))
-
-    mask1 = 0
-    mask2 = 0
-
-    for cat in ("TRACE_FRM", "TRACE_RAW"):
-      trc = os.environ.get("PN_%s" % cat)
-      if trc and trc.lower() in ("1", "2", "yes", "true"):
-        mask1 = mask1 | getattr(Transport, cat)
-      if trc == "2":
-        mask2 = mask2 | getattr(Transport, cat)
-    t1.trace(mask1)
-    t2.trace(mask2)
-
-    return c1, c2
-
-  def link(self, name, max_frame=None, idle_timeout=None):
-    c1, c2 = self.connection()
-    if max_frame:
-      c1.transport.max_frame_size = max_frame[0]
-      c2.transport.max_frame_size = max_frame[1]
-    if idle_timeout:
-      # idle_timeout in seconds expressed as float
-      c1.transport.idle_timeout = idle_timeout[0]
-      c2.transport.idle_timeout = idle_timeout[1]
-    c1.open()
-    c2.open()
-    ssn1 = c1.session()
-    ssn1.open()
-    self.pump()
-    ssn2 = c2.session_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
-    ssn2.open()
-    self.pump()
-    snd = ssn1.sender(name)
-    rcv = ssn2.receiver(name)
-    return snd, rcv
-
-  def cleanup(self):
-    self._wires = []
-
-  def pump(self, buffer_size=OUTPUT_SIZE):
-    for c1, t1, c2, t2 in self._wires:
-      pump(t1, t2, buffer_size)
-
-class ConnectionTest(Test):
-
-  def setUp(self):
-    gc.enable()
-    self.c1, self.c2 = self.connection()
-
-  def cleanup(self):
-    # release resources created by this class
-    super(ConnectionTest, self).cleanup()
-    self.c1 = None
-    self.c2 = None
-
-  def tearDown(self):
-    self.cleanup()
-    gc.collect()
-    assert not gc.garbage
-
-  def test_open_close(self):
-    assert self.c1.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-
-    self.c1.open()
-    self.pump()
-
-    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-    assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
-
-    self.c2.open()
-    self.pump()
-
-    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.c1.close()
-    self.pump()
-
-    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-    self.c2.close()
-    self.pump()
-
-    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert self.c2.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-  def test_simultaneous_open_close(self):
-    assert self.c1.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-
-    self.c1.open()
-    self.c2.open()
-
-    self.pump()
-
-    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.c1.close()
-    self.c2.close()
-
-    self.pump()
-
-    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert self.c2.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-  def test_capabilities(self):
-    self.c1.offered_capabilities = Array(UNDESCRIBED, Data.SYMBOL,
-                                         symbol("O_one"),
-                                         symbol("O_two"),
-                                         symbol("O_three"))
-
-    self.c1.desired_capabilities = Array(UNDESCRIBED, Data.SYMBOL,
-                                         symbol("D_one"),
-                                         symbol("D_two"),
-                                         symbol("D_three"))
-    self.c1.open()
-
-    assert self.c2.remote_offered_capabilities is None
-    assert self.c2.remote_desired_capabilities is None
-
-    self.pump()
-
-    assert self.c2.remote_offered_capabilities == self.c1.offered_capabilities, \
-        (self.c2.remote_offered_capabilities, self.c1.offered_capabilities)
-    assert self.c2.remote_desired_capabilities == self.c1.desired_capabilities, \
-        (self.c2.remote_desired_capabilities, self.c1.desired_capabilities)
-
-  def test_condition(self):
-    self.c1.open()
-    self.c2.open()
-    self.pump()
-    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
-    self.c1.condition = cond
-    self.c1.close()
-
-    self.pump()
-
-    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-    rcond = self.c2.remote_condition
-    assert rcond == cond, (rcond, cond)
-
-  def test_properties(self, p1={symbol("key"): symbol("value")}, p2=None):
-    self.c1.properties = p1
-    self.c2.properties = p2
-    self.c1.open()
-    self.c2.open()
-    self.pump()
-
-    assert self.c2.remote_properties == p1, (self.c2.remote_properties, p1)
-    assert self.c1.remote_properties == p2, (self.c2.remote_properties, p2)
-
-  # The proton implementation limits channel_max to 32767.
-  # If I set the application's limit lower than that, I should 
-  # get my wish.  If I set it higher -- not.
-  def test_channel_max_low(self, value=1234):
-    self.c1.transport.channel_max = value
-    self.c1.open()
-    self.pump()
-    assert self.c1.transport.channel_max == value, (self.c1.transport.channel_max, value)
-
-  def test_channel_max_high(self, value=65535):
-    self.c1.transport.channel_max = value
-    self.c1.open()
-    self.pump()
-    assert self.c1.transport.channel_max == 32767, (self.c1.transport.channel_max, value)
-
-  def test_channel_max_raise_and_lower(self):
-    upper_limit = 32767
-
-    # It's OK to lower the max below upper_limit.
-    self.c1.transport.channel_max = 12345
-    assert self.c1.transport.channel_max == 12345
-
-    # But it won't let us raise the limit above PN_IMPL_CHANNEL_MAX.
-    self.c1.transport.channel_max = 65535
-    assert self.c1.transport.channel_max == upper_limit
-
-    # send the OPEN frame
-    self.c1.open()
-    self.pump()
-
-    # Now it's too late to make any change, because
-    # we have already sent the OPEN frame.
-    try:
-      self.c1.transport.channel_max = 666
-      assert False, "expected session exception"
-    except:
-      pass
-
-    assert self.c1.transport.channel_max == upper_limit
-
-
-  # TODO: Currently failing test - PROTON-1759 - skip
-  def test_channel_max_limits_sessions(self):
-    raise Skipped('Test fails - PROTON-1759')
-    # This is an index -- so max number of channels should be 1.
-    self.c1.transport.channel_max = 0
-    self.c1.open()
-    self.c2.open()
-    ssn_0 = self.c2.session()
-    assert ssn_0 != None
-    ssn_0.open()
-    self.pump()
-    try:
-      ssn_1 = self.c2.session()
-      ssn_1.open()
-      self.pump()
-      assert False, "expected session exception"
-    except SessionException:
-      pass
-
-  def test_cleanup(self):
-    self.c1.open()
-    self.c2.open()
-    self.pump()
-    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    t1 = self.c1.transport
-    t2 = self.c2.transport
-    c2 = self.c2
-    self.c1.close()
-    # release all references to C1, except that held by the transport
-    self.cleanup()
-    gc.collect()
-    # transport should flush last state from C1:
-    pump(t1, t2)
-    assert c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-  def test_user_config(self):
-    self.c1.user = "vindaloo"
-    self.c1.password = "secret"
-    self.c1.open()
-    self.pump()
-
-    self.c2.user = "leela"
-    self.c2.password = "trustno1"
-    self.c2.open()
-    self.pump()
-
-    assert self.c1.user == "vindaloo", self.c1.user
-    assert self.c1.password == None, self.c1.password
-    assert self.c2.user == "leela", self.c2.user
-    assert self.c2.password == None, self.c2.password
-
-class SessionTest(Test):
-
-  def setUp(self):
-    gc.enable()
-    self.c1, self.c2 = self.connection()
-    self.ssn = self.c1.session()
-    self.c1.open()
-    self.c2.open()
-
-  def cleanup(self):
-    # release resources created by this class
-    super(SessionTest, self).cleanup()
-    self.c1 = None
-    self.c2 = None
-    self.ssn = None
-
-  def tearDown(self):
-    self.cleanup()
-    gc.collect()
-    assert not gc.garbage
-
-  def test_open_close(self):
-    assert self.ssn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-
-    self.ssn.open()
-
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-
-    self.pump()
-
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-
-    ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
-
-    assert ssn != None
-    assert ssn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-
-    ssn.open()
-
-    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-
-    self.pump()
-
-    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    ssn.close()
-
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.pump()
-
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-    self.ssn.close()
-
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-    self.pump()
-
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-  def test_simultaneous_close(self):
-    self.ssn.open()
-    self.pump()
-    ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
-    assert ssn != None
-    ssn.open()
-    self.pump()
-
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.ssn.close()
-    ssn.close()
-
-    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-
-    self.pump()
-
-    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-  def test_closing_connection(self):
-    self.ssn.open()
-    self.pump()
-    self.c1.close()
-    self.pump()
-    self.ssn.close()
-    self.pump()
-
-  def test_condition(self):
-    self.ssn.open()
-    self.pump()
-    ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
-    assert ssn != None
-    ssn.open()
-    self.pump()
-
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
-    self.ssn.condition = cond
-    self.ssn.close()
-
-    self.pump()
-
-    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-    rcond = ssn.remote_condition
-    assert rcond == cond, (rcond, cond)
-
-  def test_cleanup(self):
-    snd, rcv = self.link("test-link")
-    snd.open()
-    rcv.open()
-    self.pump()
-    snd_ssn = snd.session
-    rcv_ssn = rcv.session
-    assert rcv_ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    self.ssn = None
-    snd_ssn.close()
-    snd_ssn.free()
-    del snd_ssn
-    gc.collect()
-    self.pump()
-    assert rcv_ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-  def test_reopen_on_same_session_without_free(self):
-    """
-    confirm that a link is correctly opened when attaching to a previously
-    closed link *that has not been freed yet* on the same session
-    """
-    self.ssn.open()
-    self.pump()
-
-    ssn2 = self.c2.session_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
-    ssn2.open()
-    self.pump()
-    snd = self.ssn.sender("test-link")
-    rcv = ssn2.receiver("test-link")
-
-    assert snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-
-    snd.open()
-    rcv.open()
-    self.pump()
-
-    assert snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    snd.close()
-    rcv.close()
-    self.pump()
-
-    assert snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-    snd = self.ssn.sender("test-link")
-    rcv = ssn2.receiver("test-link")
-    assert snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-
-    snd.open()
-    rcv.open()
-    self.pump()
-
-    assert snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-  def test_set_get_outgoing_window(self):
-    assert self.ssn.outgoing_window == 2147483647
-
-    self.ssn.outgoing_window = 1024
-    assert self.ssn.outgoing_window == 1024
-
-
-class LinkTest(Test):
-
-  def setUp(self):
-    gc.enable()
-    self.snd, self.rcv = self.link("test-link")
-
-  def cleanup(self):
-    # release resources created by this class
-    super(LinkTest, self).cleanup()
-    self.snd = None
-    self.rcv = None
-
-  def tearDown(self):
-    self.cleanup()
-    gc.collect()
-    assert not gc.garbage, gc.garbage
-
-  def test_open_close(self):
-    assert self.snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-
-    self.snd.open()
-
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
-
-    self.rcv.open()
-
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.snd.close()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-    self.rcv.close()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-  def test_simultaneous_open_close(self):
-    assert self.snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-
-    self.snd.open()
-    self.rcv.open()
-
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.snd.close()
-    self.rcv.close()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-  def test_multiple(self):
-    rcv = self.snd.session.receiver("second-rcv")
-    assert rcv.name == "second-rcv"
-    self.snd.open()
-    rcv.open()
-    self.pump()
-    c2 = self.rcv.session.connection
-    l = c2.link_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
-    while l:
-      l.open()
-      l = l.next(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
-    self.pump()
-
-    assert self.snd
-    assert rcv
-    self.snd.close()
-    rcv.close()
-    ssn = rcv.session
-    conn = ssn.connection
-    ssn.close()
-    conn.close()
-    self.pump()
-
-  def test_closing_session(self):
-    self.snd.open()
-    self.rcv.open()
-    ssn1 = self.snd.session
-    self.pump()
-    ssn1.close()
-    self.pump()
-    self.snd.close()
-    self.pump()
-
-  def test_closing_connection(self):
-    self.snd.open()
-    self.rcv.open()
-    ssn1 = self.snd.session
-    c1 = ssn1.connection
-    self.pump()
-    c1.close()
-    self.pump()
-    self.snd.close()
-    self.pump()
-
-  def assertEqualTermini(self, t1, t2):
-    assert t1.type == t2.type, (t1.type, t2.type)
-    assert t1.address == t2.address, (t1.address, t2.address)
-    assert t1.durability == t2.durability, (t1.durability, t2.durability)
-    assert t1.expiry_policy == t2.expiry_policy, (t1.expiry_policy, t2.expiry_policy)
-    assert t1.timeout == t2.timeout, (t1.timeout, t2.timeout)
-    assert t1.dynamic == t2.dynamic, (t1.dynamic, t2.dynamic)
-    for attr in ["properties", "capabilities", "outcomes", "filter"]:
-      d1 = getattr(t1, attr)
-      d2 = getattr(t2, attr)
-      assert d1.format() == d2.format(), (attr, d1.format(), d2.format())
-
-  def _test_source_target(self, config_source, config_target):
-    if config_source is None:
-      self.snd.source.type = Terminus.UNSPECIFIED
-    else:
-      config_source(self.snd.source)
-    if config_target is None:
-      self.snd.target.type = Terminus.UNSPECIFIED
-    else:
-      config_target(self.snd.target)
-    self.snd.open()
-    self.pump()
-    self.assertEqualTermini(self.rcv.remote_source, self.snd.source)
-    self.assertEqualTermini(self.rcv.remote_target, self.snd.target)
-    self.rcv.target.copy(self.rcv.remote_target)
-    self.rcv.source.copy(self.rcv.remote_source)
-    self.rcv.open()
-    self.pump()
-    self.assertEqualTermini(self.snd.remote_target, self.snd.target)
-    self.assertEqualTermini(self.snd.remote_source, self.snd.source)
-
-  def test_source_target(self):
-    self._test_source_target(TerminusConfig(address="source"),
-                             TerminusConfig(address="target"))
-
-  def test_source(self):
-    self._test_source_target(TerminusConfig(address="source"), None)
-
-  def test_target(self):
-    self._test_source_target(None, TerminusConfig(address="target"))
-
-  def test_coordinator(self):
-    self._test_source_target(None, TerminusConfig(type=Terminus.COORDINATOR))
-
-  def test_source_target_full(self):
-    self._test_source_target(TerminusConfig(address="source",
-                                            timeout=3,
-                                            dist_mode=Terminus.DIST_MODE_MOVE,
-                                            filter=[("int", 1), ("symbol", "two"), ("string", "three")],
-                                            capabilities=["one", "two", "three"]),
-                             TerminusConfig(address="source",
-                                            timeout=7,
-                                            capabilities=[]))
-  def test_distribution_mode(self):
-    self._test_source_target(TerminusConfig(address="source",
-                                            dist_mode=Terminus.DIST_MODE_COPY),
-                             TerminusConfig(address="target"))
-    assert self.rcv.remote_source.distribution_mode == Terminus.DIST_MODE_COPY
-    assert self.rcv.remote_target.distribution_mode == Terminus.DIST_MODE_UNSPECIFIED
-
-  def test_dynamic_link(self):
-    self._test_source_target(TerminusConfig(address=None, dynamic=True), None)
-    assert self.rcv.remote_source.dynamic
-    assert self.rcv.remote_source.address is None
-
-  def test_condition(self):
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
-    self.snd.condition = cond
-    self.snd.close()
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-    rcond = self.rcv.remote_condition
-    assert rcond == cond, (rcond, cond)
-
-  def test_settle_mode(self):
-    self.snd.snd_settle_mode = Link.SND_UNSETTLED
-    assert self.snd.snd_settle_mode == Link.SND_UNSETTLED
-    self.rcv.rcv_settle_mode = Link.RCV_SECOND
-    assert self.rcv.rcv_settle_mode == Link.RCV_SECOND
-
-    assert self.snd.remote_rcv_settle_mode != Link.RCV_SECOND
-    assert self.rcv.remote_snd_settle_mode != Link.SND_UNSETTLED
-
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-    assert self.snd.remote_rcv_settle_mode == Link.RCV_SECOND
-    assert self.rcv.remote_snd_settle_mode == Link.SND_UNSETTLED
-
-  def test_max_message_size(self):
-    assert self.snd.max_message_size == 0
-    assert self.rcv.remote_max_message_size == 0
-    self.snd.max_message_size = 13579
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-    assert self.rcv.remote_max_message_size == 13579
-
-  def test_cleanup(self):
-    snd, rcv = self.link("test-link")
-    snd.open()
-    rcv.open()
-    self.pump()
-    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    snd.close()
-    snd.free()
-    del snd
-    gc.collect()
-    self.pump()
-    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-class TerminusConfig:
-
-  def __init__(self, type=None, address=None, timeout=None, durability=None,
-               filter=None, capabilities=None, dynamic=False, dist_mode=None):
-    self.address = address
-    self.timeout = timeout
-    self.durability = durability
-    self.filter = filter
-    self.capabilities = capabilities
-    self.dynamic = dynamic
-    self.dist_mode = dist_mode
-    self.type = type
-
-  def __call__(self, terminus):
-    if self.type is not None:
-      terminus.type = self.type
-    if self.address is not None:
-      terminus.address = self.address
-    if self.timeout is not None:
-      terminus.timeout = self.timeout
-    if self.durability is not None:
-      terminus.durability = self.durability
-    if self.capabilities is not None:
-      terminus.capabilities.put_array(False, Data.SYMBOL)
-      terminus.capabilities.enter()
-      for c in self.capabilities:
-        terminus.capabilities.put_symbol(c)
-    if self.filter is not None:
-      terminus.filter.put_map()
-      terminus.filter.enter()
-      for (t, v) in self.filter:
-        setter = getattr(terminus.filter, "put_%s" % t)
-        setter(v)
-    if self.dynamic:
-      terminus.dynamic = True
-    if self.dist_mode is not None:
-      terminus.distribution_mode = self.dist_mode
-
-class TransferTest(Test):
-
-  def setUp(self):
-    gc.enable()
-    self.snd, self.rcv = self.link("test-link")
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-  def cleanup(self):
-    # release resources created by this class
-    super(TransferTest, self).cleanup()
-    self.c1 = None
-    self.c2 = None
-    self.snd = None
-    self.rcv = None
-
-  def tearDown(self):
-    self.cleanup()
-    gc.collect()
-    assert not gc.garbage
-
-  def test_work_queue(self):
-    assert self.c1.work_head is None
-    self.snd.delivery("tag")
-    assert self.c1.work_head is None
-    self.rcv.flow(1)
-    self.pump()
-    d = self.c1.work_head
-    assert d is not None
-    tag = d.tag
-    assert tag == "tag", tag
-    assert d.writable
-
-    n = self.snd.send(b"this is a test")
-    assert self.snd.advance()
-    assert self.c1.work_head is None
-
-    self.pump()
-
-    d = self.c2.work_head
-    assert d.tag == "tag"
-    assert d.readable
-
-  def test_multiframe(self):
-    self.rcv.flow(1)
-    self.snd.delivery("tag")
-    msg = b"this is a test"
-    n = self.snd.send(msg)
-    assert n == len(msg)
-
-    self.pump()
-
-    d = self.rcv.current
-    assert d
-    assert d.tag == "tag", repr(d.tag)
-    assert d.readable
-
-    binary = self.rcv.recv(1024)
-    assert binary == msg, (binary, msg)
-
-    binary = self.rcv.recv(1024)
-    assert binary == b""
-
-    msg = b"this is more"
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    binary = self.rcv.recv(1024)
-    assert binary == msg, (binary, msg)
-
-    binary = self.rcv.recv(1024)
-    assert binary is None
-
-  def test_disposition(self):
-    self.rcv.flow(1)
-
-    self.pump()
-
-    sd = self.snd.delivery("tag")
-    msg = b"this is a test"
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    rd = self.rcv.current
-    assert rd is not None
-    assert rd.tag == sd.tag
-    rmsg = self.rcv.recv(1024)
-    assert rmsg == msg
-    rd.update(Delivery.ACCEPTED)
-
-    self.pump()
-
-    rdisp = sd.remote_state
-    ldisp = rd.local_state
-    assert rdisp == ldisp == Delivery.ACCEPTED, (rdisp, ldisp)
-    assert sd.updated
-
-    sd.update(Delivery.ACCEPTED)
-
-    self.pump()
-
-    assert sd.local_state == rd.remote_state == Delivery.ACCEPTED
-    sd.settle()
-
-  def test_delivery_id_ordering(self):
-    self.rcv.flow(1024)
-    self.pump(buffer_size=64*1024)
-
-    #fill up delivery buffer on sender
-    for m in range(1024):
-      sd = self.snd.delivery("tag%s" % m)
-      msg = ("message %s" % m).encode('ascii')
-      n = self.snd.send(msg)
-      assert n == len(msg)
-      assert self.snd.advance()
-
-    self.pump(buffer_size=64*1024)
-
-    #receive a session-windows worth of messages and accept them
-    for m in range(1024):
-      rd = self.rcv.current
-      assert rd is not None, m
-      assert rd.tag == ("tag%s" % m), (rd.tag, m)
-      msg = self.rcv.recv(1024)
-      assert msg == ("message %s" % m).encode('ascii'), (msg, m)
-      rd.update(Delivery.ACCEPTED)
-      rd.settle()
-
-    self.pump(buffer_size=64*1024)
-
-    #add some new deliveries
-    for m in range(1024, 1450):
-      sd = self.snd.delivery("tag%s" % m)
-      msg = ("message %s" % m).encode('ascii')
-      n = self.snd.send(msg)
-      assert n == len(msg)
-      assert self.snd.advance()
-
-    #handle all disposition changes to sent messages
-    d = self.c1.work_head
-    while d:
-      next_d = d.work_next
-      if d.updated:
-        d.update(Delivery.ACCEPTED)
-        d.settle()
-      d = next_d
-
-    #submit some more deliveries
-    for m in range(1450, 1500):
-      sd = self.snd.delivery("tag%s" % m)
-      msg = ("message %s" % m).encode('ascii')
-      n = self.snd.send(msg)
-      assert n == len(msg)
-      assert self.snd.advance()
-
-    self.pump(buffer_size=64*1024)
-    self.rcv.flow(1024)
-    self.pump(buffer_size=64*1024)
-
-    #verify remaining messages can be received and accepted
-    for m in range(1024, 1500):
-      rd = self.rcv.current
-      assert rd is not None, m
-      assert rd.tag == ("tag%s" % m), (rd.tag, m)
-      msg = self.rcv.recv(1024)
-      assert msg == ("message %s" % m).encode('ascii'), (msg, m)
-      rd.update(Delivery.ACCEPTED)
-      rd.settle()
-
-  def test_cleanup(self):
-    self.rcv.flow(10)
-    self.pump()
-
-    for x in range(10):
-        self.snd.delivery("tag%d" % x)
-        msg = b"this is a test"
-        n = self.snd.send(msg)
-        assert n == len(msg)
-        assert self.snd.advance()
-    self.snd.close()
-    self.snd.free()
-    self.snd = None
-    gc.collect()
-
-    self.pump()
-
-    for x in range(10):
-        rd = self.rcv.current
-        assert rd is not None
-        assert rd.tag == "tag%d" % x
-        rmsg = self.rcv.recv(1024)
-        assert self.rcv.advance()
-        assert rmsg == msg
-        # close of snd should've settled:
-        assert rd.settled
-        rd.settle()
-
-class MaxFrameTransferTest(Test):
-
-  def setUp(self):
-    pass
-
-  def cleanup(self):
-    # release resources created by this class
-    super(MaxFrameTransferTest, self).cleanup()
-    self.c1 = None
-    self.c2 = None
-    self.snd = None
-    self.rcv = None
-
-  def tearDown(self):
-    self.cleanup()
-
-  def message(self, size):
-    parts = []
-    for i in range(size):
-      parts.append(str(i))
-    return "/".join(parts)[:size].encode("utf-8")
-
-  def testMinFrame(self):
-    """
-    Configure receiver to support minimum max-frame as defined by AMQP-1.0.
-    Verify transfer of messages larger than 512.
-    """
-    self.snd, self.rcv = self.link("test-link", max_frame=[0,512])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-    assert self.rcv.session.connection.transport.max_frame_size == 512
-    assert self.snd.session.connection.transport.remote_max_frame_size == 512
-
-    self.rcv.flow(1)
-    self.snd.delivery("tag")
-    msg = self.message(513)
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    binary = self.rcv.recv(513)
-    assert binary == msg
-
-    binary = self.rcv.recv(1024)
-    assert binary == None
-
-  def testOddFrame(self):
-    """
-    Test an odd sized max limit with data that will require multiple frames to
-    be transfered.
-    """
-    self.snd, self.rcv = self.link("test-link", max_frame=[0,521])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-    assert self.rcv.session.connection.transport.max_frame_size == 521
-    assert self.snd.session.connection.transport.remote_max_frame_size == 521
-
-    self.rcv.flow(2)
-    self.snd.delivery("tag")
-    msg = ("X" * 1699).encode('utf-8')
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    binary = self.rcv.recv(1699)
-    assert binary == msg
-
-    binary = self.rcv.recv(1024)
-    assert binary == None
-
-    self.rcv.advance()
-
-    self.snd.delivery("gat")
-    msg = self.message(1426)
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    binary = self.rcv.recv(1426)
-    assert binary == msg
-
-    self.pump()
-
-    binary = self.rcv.recv(1024)
-    assert binary == None
-
-  def testSendQueuedMultiFrameMessages(self, sendSingleFrameMsg = False):
-    """
-    Test that multiple queued messages on the same link
-    with multi-frame content are sent correctly. Use an
-    odd max frame size, send enough data to use many.
-    """
-    self.snd, self.rcv = self.link("test-link", max_frame=[0,517])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-    assert self.rcv.session.connection.transport.max_frame_size == 517
-    assert self.snd.session.connection.transport.remote_max_frame_size == 517
-
-    self.rcv.flow(5)
-
-    self.pump()
-
-    # Send a delivery with 5 frames, all bytes as X1234
-    self.snd.delivery("tag")
-    msg = ("X1234" * 425).encode('utf-8')
-    assert 2125 == len(msg)
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    # Send a delivery with 5 frames, all bytes as Y5678
-    self.snd.delivery("tag2")
-    msg2 = ("Y5678" * 425).encode('utf-8')
-    assert 2125 == len(msg2)
-    n = self.snd.send(msg2)
-    assert n == len(msg2)
-    assert self.snd.advance()
-
-    self.pump()
-
-    if sendSingleFrameMsg:
-        # Send a delivery with 1 frame
-        self.snd.delivery("tag3")
-        msg3 = ("Z").encode('utf-8')
-        assert 1 == len(msg3)
-        n = self.snd.send(msg3)
-        assert n == len(msg3)
-        assert self.snd.advance()
-        self.pump()
-
-    binary = self.rcv.recv(5000)
-    self.assertEqual(binary, msg)
-
-    self.rcv.advance()
-
-    binary2 = self.rcv.recv(5000)
-    self.assertEqual(binary2, msg2)
-
-    self.rcv.advance()
-
-    if sendSingleFrameMsg:
-        binary3 = self.rcv.recv(5000)
-        self.assertEqual(binary3, msg3)
-        self.rcv.advance()
-
-    self.pump()
-
-  def testSendQueuedMultiFrameMessagesThenSingleFrameMessage(self):
-    self.testSendQueuedMultiFrameMessages(sendSingleFrameMsg = True)
-
-  def testBigMessage(self):
-    """
-    Test transferring a big message.
-    """
-    self.snd, self.rcv = self.link("test-link")
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-    self.rcv.flow(2)
-    self.snd.delivery("tag")
-    msg = self.message(1024*256)
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    binary = self.rcv.recv(1024*256)
-    assert binary == msg
-
-    binary = self.rcv.recv(1024)
-    assert binary == None
-
-
-class IdleTimeoutTest(Test):
-
-  def setUp(self):
-    pass
-
-  def cleanup(self):
-    # release resources created by this class
-    super(IdleTimeoutTest, self).cleanup()
-    self.snd = None
-    self.rcv = None
-    self.c1 = None
-    self.c2 = None
-
-  def tearDown(self):
-    self.cleanup()
-
-  def message(self, size):
-    parts = []
-    for i in range(size):
-      parts.append(str(i))
-    return "/".join(parts)[:size]
-
-  def testGetSet(self):
-    """
-    Verify the configuration and negotiation of the idle timeout.
-    """
-
-    self.snd, self.rcv = self.link("test-link", idle_timeout=[1.0,2.0])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-    # proton advertises 1/2 the configured timeout to the peer:
-    assert self.rcv.session.connection.transport.idle_timeout == 2.0
-    assert self.rcv.session.connection.transport.remote_idle_timeout == 0.5
-    assert self.snd.session.connection.transport.idle_timeout == 1.0
-    assert self.snd.session.connection.transport.remote_idle_timeout == 1.0
-
-  def testTimeout(self):
-    """
-    Verify the AMQP Connection idle timeout.
-    """
-
-    # snd will timeout the Connection if no frame is received within 1000 ticks
-    self.snd, self.rcv = self.link("test-link", idle_timeout=[1.0,0])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-    t_snd = self.snd.session.connection.transport
-    t_rcv = self.rcv.session.connection.transport
-    assert t_rcv.idle_timeout == 0.0
-    # proton advertises 1/2 the timeout (see spec)
-    assert t_rcv.remote_idle_timeout == 0.5
-    assert t_snd.idle_timeout == 1.0
-    assert t_snd.remote_idle_timeout == 0.0
-
-    sndr_frames_in = t_snd.frames_input
-    rcvr_frames_out = t_rcv.frames_output
-
-    # at t+1msec, nothing should happen:
-    clock = 0.001
-    assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
-    assert t_rcv.tick(clock) == 0.251,  "deadline to send keepalive"
-    self.pump()
-    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
-
-    # at one tick from expected idle frame send, nothing should happen:
-    clock = 0.250
-    assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
-    assert t_rcv.tick(clock) == 0.251,  "deadline to send keepalive"
-    self.pump()
-    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
-
-    # this should cause rcvr to expire and send a keepalive
-    clock = 0.251
-    assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
-    assert t_rcv.tick(clock) == 0.501, "deadline to send keepalive"
-    self.pump()
-    sndr_frames_in += 1
-    rcvr_frames_out += 1
-    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
-    assert rcvr_frames_out == t_rcv.frames_output, "unexpected frame"
-
-    # since a keepalive was received, sndr will rebase its clock against this tick:
-    # and the receiver should not change its deadline
-    clock = 0.498
-    assert t_snd.tick(clock) == 1.498, "deadline for remote timeout"
-    assert t_rcv.tick(clock) == 0.501, "deadline to send keepalive"
-    self.pump()
-    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
-
-    # now expire sndr
-    clock = 1.499
-    t_snd.tick(clock)
-    self.pump()
-    assert self.c2.state & Endpoint.REMOTE_CLOSED
-    assert self.c2.remote_condition.name == "amqp:resource-limit-exceeded"
-
-class CreditTest(Test):
-
-  def setUp(self):
-    self.snd, self.rcv = self.link("test-link", max_frame=(16*1024, 16*1024))
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-  def cleanup(self):
-    # release resources created by this class
-    super(CreditTest, self).cleanup()
-    self.c1 = None
-    self.snd = None
-    self.c2 = None
-    self.rcv2 = None
-    self.snd2 = None
-
-  def tearDown(self):
-    self.cleanup()
-
-  def testCreditSender(self, count=1024):
-    credit = self.snd.credit
-    assert credit == 0, credit
-    self.rcv.flow(10)
-    self.pump()
-    credit = self.snd.credit
-    assert credit == 10, credit
-
-    self.rcv.flow(count)
-    self.pump()
-    credit = self.snd.credit
-    assert credit == 10 + count, credit
-
-  def testCreditReceiver(self):
-    self.rcv.flow(10)
-    self.pump()
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    d = self.snd.delivery("tag")
-    assert d
-    assert self.snd.advance()
-    self.pump()
-    assert self.rcv.credit == 10, self.rcv.credit
-    assert self.rcv.queued == 1, self.rcv.queued
-    c = self.rcv.current
-    assert c.tag == "tag", c.tag
-    assert self.rcv.advance()
-    assert self.rcv.credit == 9, self.rcv.credit
-    assert self.rcv.queued == 0, self.rcv.queued
-
-  def _testBufferingOnClose(self, a, b):
-    for i in range(10):
-      d = self.snd.delivery("tag-%s" % i)
-      assert d
-      d.settle()
-    self.pump()
-    assert self.snd.queued == 10
-
-    endpoints = {"connection": (self.c1, self.c2),
-                 "session": (self.snd.session, self.rcv.session),
-                 "link": (self.snd, self.rcv)}
-
-    local_a, remote_a = endpoints[a]
-    local_b, remote_b = endpoints[b]
-
-    remote_b.close()
-    self.pump()
-    assert local_b.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-    local_a.close()
-    self.pump()
-    assert remote_a.state & Endpoint.REMOTE_CLOSED
-    assert self.snd.queued == 10
-
-  def testBufferingOnCloseLinkLink(self):
-    self._testBufferingOnClose("link", "link")
-
-  def testBufferingOnCloseLinkSession(self):
-    self._testBufferingOnClose("link", "session")
-
-  def testBufferingOnCloseLinkConnection(self):
-    self._testBufferingOnClose("link", "connection")
-
-  def testBufferingOnCloseSessionLink(self):
-    self._testBufferingOnClose("session", "link")
-
-  def testBufferingOnCloseSessionSession(self):
-    self._testBufferingOnClose("session", "session")
-
-  def testBufferingOnCloseSessionConnection(self):
-    self._testBufferingOnClose("session", "connection")
-
-  def testBufferingOnCloseConnectionLink(self):
-    self._testBufferingOnClose("connection", "link")
-
-  def testBufferingOnCloseConnectionSession(self):
-    self._testBufferingOnClose("connection", "session")
-
-  def testBufferingOnCloseConnectionConnection(self):
-    self._testBufferingOnClose("connection", "connection")
-
-  def testFullDrain(self):
-    assert self.rcv.credit == 0
-    assert self.snd.credit == 0
-    self.rcv.drain(10)
-    assert self.rcv.draining()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 0
-    self.pump()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 10
-    assert self.rcv.draining()
-    self.snd.drained()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 0
-    assert self.rcv.draining()
-    self.pump()
-    assert self.rcv.credit == 0
-    assert self.snd.credit == 0
-    assert not self.rcv.draining()
-    drained = self.rcv.drained()
-    assert drained == 10, drained
-
-  def testPartialDrain(self):
-    self.rcv.drain(2)
-    assert self.rcv.draining()
-    self.pump()
-
-    d = self.snd.delivery("tag")
-    assert d
-    assert self.snd.advance()
-    self.snd.drained()
-    assert self.rcv.draining()
-    self.pump()
-    assert not self.rcv.draining()
-
-    c = self.rcv.current
-    assert self.rcv.queued == 1, self.rcv.queued
-    assert c.tag == d.tag, c.tag
-    assert self.rcv.advance()
-    assert not self.rcv.current
-    assert self.rcv.credit == 0, self.rcv.credit
-    assert not self.rcv.draining()
-    drained = self.rcv.drained()
-    assert drained == 1, drained
-
-  def testDrainFlow(self):
-    assert self.rcv.credit == 0
-    assert self.snd.credit == 0
-    self.rcv.drain(10)
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 0
-    self.pump()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 10
-    self.snd.drained()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 0
-    self.pump()
-    assert self.rcv.credit == 0
-    assert self.snd.credit == 0
-    self.rcv.flow(10)
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 0
-    self.pump()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 10
-    self.snd.drained()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 10
-    self.pump()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 10
-    drained = self.rcv.drained()
-    assert drained == 10, drained
-
-  def testNegative(self):
-    assert self.snd.credit == 0
-    d = self.snd.delivery("tag")
-    assert d
-    assert self.snd.advance()
-    self.pump()
-
-    assert self.rcv.credit == 0
-    assert self.rcv.queued == 0
-
-    self.rcv.flow(1)
-    assert self.rcv.credit == 1
-    assert self.rcv.queued == 0
-    self.pump()
-    assert self.rcv.credit == 1
-    assert self.rcv.queued == 1, self.rcv.queued
-
-    c = self.rcv.current
-    assert c
-    assert c.tag == "tag"
-    assert self.rcv.advance()
-    assert self.rcv.credit == 0
-    assert self.rcv.queued == 0
-
-  def testDrainZero(self):
-    assert self.snd.credit == 0
-    assert self.rcv.credit == 0
-    assert self.rcv.queued == 0
-    drained = self.rcv.drained()
-    assert drained == 0
-
-    self.rcv.flow(10)
-    self.pump()
-    assert self.snd.credit == 10
-    assert self.rcv.credit == 10
-    assert self.rcv.queued == 0
-
-    self.snd.drained()
-    self.pump()
-    assert self.snd.credit == 10
-    assert self.rcv.credit == 10
-    assert self.rcv.queued == 0
-    drained = self.rcv.drained()
-    assert drained == 0
-
-    self.rcv.drain(0)
-    assert self.snd.credit == 10
-    assert self.rcv.credit == 10
-    assert self.rcv.queued == 0
-
-    self.pump()
-
-    assert self.snd.credit == 10
-    assert self.rcv.credit == 10
-    assert self.rcv.queued == 0
-
-    self.snd.drained()
-    assert self.snd.credit == 0
-    assert self.rcv.credit == 10
-    assert self.rcv.queued == 0
-    drained = self.rcv.drained()
-    assert drained == 0
-    self.pump()
-
-    assert self.snd.credit == 0
-    assert self.rcv.credit == 0
-    assert self.rcv.queued == 0
-    drained = self.rcv.drained()
-    assert drained == 10
-
-
-  def testDrainOrder(self):
-    """ Verify drain/drained works regardless of ordering.  See PROTON-401
-    """
-    assert self.snd.credit == 0
-    assert self.rcv.credit == 0
-    assert self.rcv.queued == 0
-
-    #self.rcv.session.connection.transport.trace(Transport.TRACE_FRM)
-    #self.snd.session.connection.transport.trace(Transport.TRACE_FRM)
-
-    ## verify that a sender that has reached the drain state will respond
-    ## promptly to a drain issued by the peer.
-    self.rcv.flow(10)
-    self.pump()
-    assert self.snd.credit == 10, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    sd = self.snd.delivery("tagA")
-    assert sd
-    n = self.snd.send(b"A")
-    assert n == 1
-    self.pump()
-    self.snd.advance()
-
-    # done sending, so signal that we are drained:
-    self.snd.drained()
-    self.pump()
-    assert self.snd.credit == 9, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    self.rcv.drain(0)
-    self.pump()
-    assert self.snd.credit == 9, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    data = self.rcv.recv(10)
-    assert data == b"A", data
-    self.rcv.advance()
-    self.pump()
-    assert self.snd.credit == 9, self.snd.credit
-    assert self.rcv.credit == 9, self.rcv.credit
-
-    self.snd.drained()
-    self.pump()
-    assert self.snd.credit == 0, self.snd.credit
-    assert self.rcv.credit == 0, self.rcv.credit
-
-    # verify that a drain requested by the peer is not "acknowledged" until
-    # after the sender has completed sending its pending messages
-
-    self.rcv.flow(10)
-    self.pump()
-    assert self.snd.credit == 10, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    sd = self.snd.delivery("tagB")
-    assert sd
-    n = self.snd.send(b"B")
-    assert n == 1
-    self.snd.advance()
-    self.pump()
-    assert self.snd.credit == 9, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    self.rcv.drain(0)
-    self.pump()
-    assert self.snd.credit == 9, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    sd = self.snd.delivery("tagC")
-    assert sd
-    n = self.snd.send(b"C")
-    assert n == 1
-    self.snd.advance()
-    self.pump()
-    assert self.snd.credit == 8, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    # now that the sender has finished sending everything, it can signal
-    # drained
-    self.snd.drained()
-    self.pump()
-    assert self.snd.credit == 0, self.snd.credit
-    assert self.rcv.credit == 2, self.rcv.credit
-
-    data = self.rcv.recv(10)
-    assert data == b"B", data
-    self.rcv.advance()
-    data = self.rcv.recv(10)
-    assert data == b"C", data
-    self.rcv.advance()
-    self.pump()
-    assert self.snd.credit == 0, self.snd.credit
-    assert self.rcv.credit == 0, self.rcv.credit
-
-
-  def testPushback(self, count=10):
-    assert self.snd.credit == 0
-    assert self.rcv.credit == 0
-
-    self.rcv.flow(count)
-    self.pump()
-
-    for i in range(count):
-      d = self.snd.delivery("tag%s" % i)
-      assert d
-      self.snd.advance()
-
-    assert self.snd.queued == count
-    assert self.rcv.queued == 0
-    self.pump()
-    assert self.snd.queued == 0
-    assert self.rcv.queued == count
-
-    d = self.snd.delivery("extra")
-    self.snd.advance()
-
-    assert self.snd.queued == 1
-    assert self.rcv.queued == count
-    self.pump()
-    assert self.snd.queued == 1
-    assert self.rcv.queued == count
-
-  def testHeadOfLineBlocking(self):
-      self.snd2 = self.snd.session.sender("link-2")
-      self.rcv2 = self.rcv.session.receiver("link-2")
-      self.snd2.open()
-      self.rcv2.open()
-      self.pump()
-      assert self.snd2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-      assert self.rcv2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-      self.rcv.flow(5)
-      self.rcv2.flow(10)
-      self.pump()
-
-      assert self.snd.credit == 5
-      assert self.snd2.credit == 10
-
-      for i in range(10):
-          tag = "test %d" % i
-          self.snd.delivery( tag )
-          self.snd.send( tag.encode("ascii") )
-          assert self.snd.advance()
-          self.snd2.delivery( tag )
-          self.snd2.send( tag.encode("ascii") )
-          assert self.snd2.advance()
-
-      self.pump()
-
-      for i in range(5):
-          b = self.rcv.recv( 512 )
-          assert self.rcv.advance()
-          b = self.rcv2.recv( 512 )
-          assert self.rcv2.advance()
-
-      for i in range(5):
-          b = self.rcv2.recv( 512 )
-          assert self.rcv2.advance()
-
-
-
-class SessionCreditTest(Test):
-
-  def tearDown(self):
-    self.cleanup()
-
-  def testBuffering(self, count=32, size=1024, capacity=16*1024, max_frame=1024):
-    snd, rcv = self.link("test-link", max_frame=(max_frame, max_frame))
-    rcv.session.incoming_capacity = capacity
-    snd.open()
-    rcv.open()
-    rcv.flow(count)
-    self.pump()
-
-    assert count > 0
-
-    total_bytes = count * size
-
-    assert snd.session.outgoing_bytes == 0, snd.session.outgoing_bytes
-    assert rcv.session.incoming_bytes == 0, rcv.session.incoming_bytes
-    assert snd.queued == 0, snd.queued
-    assert rcv.queued == 0, rcv.queued
-
-    data = bytes(bytearray(size))
-    idx = 0
-    while snd.credit:
-      d = snd.delivery("tag%s" % idx)
-      assert d
-      n = snd.send(data)
-      assert n == size, (n, size)
-      assert snd.advance()
-      self.pump()
-      idx += 1
-
-    assert idx == count, (idx, count)
-
-    assert snd.session.outgoing_bytes < total_bytes, (snd.session.outgoing_bytes, total_bytes)
-    assert rcv.session.incoming_bytes < capacity, (rcv.session.incoming_bytes, capacity)
-    assert snd.session.outgoing_bytes + rcv.session.incoming_bytes == total_bytes, \
-        (snd.session.outgoing_bytes, rcv.session.incoming_bytes, total_bytes)
-    if snd.session.outgoing_bytes > 0:
-      available = rcv.session.incoming_capacity - rcv.session.incoming_bytes
-      assert available < max_frame, (available, max_frame)
-
-    for i in range(count):
-      d = rcv.current
-      assert d, i
-      pending = d.pending
-      before = rcv.session.incoming_bytes
-      assert rcv.advance()
-      after = rcv.session.incoming_bytes
-      assert before - after == pending, (before, after, pending)
-      snd_before = snd.session.incoming_bytes
-      self.pump()
-      snd_after = snd.session.incoming_bytes
-
-      assert rcv.session.incoming_bytes < capacity
-      if snd_before > 0:
-        assert capacity - after <= max_frame
-        assert snd_before > snd_after
-      if snd_after > 0:
-        available = rcv.session.incoming_capacity - rcv.session.incoming_bytes
-        assert available < max_frame, available
-
-  def testBufferingSize16(self):
-    self.testBuffering(size=16)
-
-  def testBufferingSize256(self):
-    self.testBuffering(size=256)
-
-  def testBufferingSize512(self):
-    self.testBuffering(size=512)
-
-  def testBufferingSize2048(self):
-    self.testBuffering(size=2048)
-
-  def testBufferingSize1025(self):
-    self.testBuffering(size=1025)
-
-  def testBufferingSize1023(self):
-    self.testBuffering(size=1023)
-
-  def testBufferingSize989(self):
-    self.testBuffering(size=989)
-
-  def testBufferingSize1059(self):
-    self.testBuffering(size=1059)
-
-  def testCreditWithBuffering(self):
-    snd, rcv = self.link("test-link", max_frame=(1024, 1024))
-    rcv.session.incoming_capacity = 64*1024
-    snd.open()
-    rcv.open()
-    rcv.flow(128)
-    self.pump()
-
-    assert snd.credit == 128, snd.credit
-    assert rcv.queued == 0, rcv.queued
-
-    idx = 0
-    while snd.credit:
-      d = snd.delivery("tag%s" % idx)
-      snd.send(("x"*1024).encode('ascii'))
-      assert d
-      assert snd.advance()
-      self.pump()
-      idx += 1
-
-    assert idx == 128, idx
-    assert rcv.queued < 128, rcv.queued
-
-    rcv.flow(1)
-    self.pump()
-    assert snd.credit == 1, snd.credit
-
-class SettlementTest(Test):
-
-  def setUp(self):
-    self.snd, self.rcv = self.link("test-link")
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-  def cleanup(self):
-    # release resources created by this class
-    super(SettlementTest, self).cleanup()
-    self.c1 = None
-    self.snd = None
-    self.c2 = None
-    self.rcv2 = None
-    self.snd2 = None
-
-  def tearDown(self):
-    self.cleanup()
-
-  def testSettleCurrent(self):
-    self.rcv.flow(10)
-    self.pump()
-
-    assert self.snd.credit == 10, self.snd.credit
-    d = self.snd.delivery("tag")
-    e = self.snd.delivery("tag2")
-    assert d
-    assert e
-    c = self.snd.current
-    assert c.tag == "tag", c.tag
-    c.settle()
-    c = self.snd.current
-    assert c.tag == "tag2", c.tag
-    c.settle()
-    c = self.snd.current
-    assert not c
-    self.pump()
-
-    c = self.rcv.current
-    assert c
-    assert c.tag == "tag", c.tag
-    assert c.settled
-    c.settle()
-    c = self.rcv.current
-    assert c
-    assert c.tag == "tag2", c.tag
-    assert c.settled
-    c.settle()
-    c = self.rcv.current
-    assert not c
-
-  def testUnsettled(self):
-    self.rcv.flow(10)
-    self.pump()
-
-    assert self.snd.unsettled == 0, self.snd.unsettled
-    assert self.rcv.unsettled == 0, self.rcv.unsettled
-
-    d = self.snd.delivery("tag")
-    assert d
-    assert self.snd.unsettled == 1, self.snd.unsettled
-    assert self.rcv.unsettled == 0, self.rcv.unsettled
-    assert self.snd.advance()
-    self.pump()
-
-    assert self.snd.unsettled == 1, self.snd.unsettled
-    assert self.rcv.unsettled == 1, self.rcv.unsettled
-
-    c = self.rcv.current
-    assert c
-    c.settle()
-
-    assert self.snd.unsettled == 1, self.snd.unsettled
-    assert self.rcv.unsettled == 0, self.rcv.unsettled
-
-  def testMultipleUnsettled(self, count=1024, size=1024):
-    self.rcv.flow(count)
-    self.pump()
-
-    assert self.snd.unsettled == 0, self.snd.unsettled
-    assert self.rcv.unsettled == 0, self.rcv.unsettled
-
-    unsettled = []
-
-    for i in range(count):
-      sd = self.snd.delivery("tag%s" % i)
-      assert sd
-      n = self.snd.send(("x"*size).encode('ascii'))
-      assert n == size, n
-      assert self.snd.advance()
-      self.pump()
-
-      rd = self.rcv.current
-      assert rd, "did not receive delivery %s" % i
-      n = rd.pending
-      b = self.rcv.recv(n)
-      assert len(b) == n, (b, n)
-      rd.update(Delivery.ACCEPTED)
-      assert self.rcv.advance()
-      self.pump()
-      unsettled.append(rd)
-
-    assert self.rcv.unsettled == count
-
-    for rd in unsettled:
-      rd.settle()
-
-  def testMultipleUnsettled2K1K(self):
-    self.testMultipleUnsettled(2048, 1024)
-
-  def testMultipleUnsettled4K1K(self):
-    self.testMultipleUnsettled(4096, 1024)
-
-  def testMultipleUnsettled1K2K(self):
-    self.testMultipleUnsettled(1024, 2048)
-
-  def testMultipleUnsettled2K2K(self):
-    self.testMultipleUnsettled(2048, 2048)
-
-  def testMultipleUnsettled4K2K(self):
-    self.testMultipleUnsettled(4096, 2048)
-
-class PipelineTest(Test):
-
-  def setUp(self):
-    self.c1, self.c2 = self.connection()
-
-  def cleanup(self):
-    # release resources created by this class
-    super(PipelineTest, self).cleanup()
-    self.c1 = None
-    self.c2 = None
-
-  def tearDown(self):
-    self.cleanup()
-
-  def test(self):
-    ssn = self.c1.session()
-    snd = ssn.sender("sender")
-    self.c1.open()
-    ssn.open()
-    snd.open()
-
-    for i in range(10):
-      t = "delivery-%s" % i
-      d = snd.delivery(t)
-      snd.send(t.encode('ascii'))
-      d.settle()
-
-    snd.close()
-    ssn.close()
-    self.c1.close()
-
-    self.pump()
-
-    state = self.c2.state
-    assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
-    ssn2 = self.c2.session_head(Endpoint.LOCAL_UNINIT)
-    assert ssn2
-    state == ssn2.state
-    assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
-    rcv = self.c2.link_head(Endpoint.LOCAL_UNINIT)
-    assert rcv
-    state = rcv.state
-    assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
-
-    self.c2.open()
-    ssn2.open()
-    rcv.open()
-    rcv.flow(10)
-    assert rcv.queued == 0, rcv.queued
-
-    self.pump()
-
-    assert rcv.queued == 10, rcv.queued
-    state = rcv.state
-    assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
-    state = ssn2.state
-    assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
-    state = self.c2.state
-    assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
-
-    for i in range(rcv.queued):
-      d = rcv.current
-      assert d
-      assert d.tag == "delivery-%s" % i
-      d.settle()
-
-    assert rcv.queued == 0, rcv.queued
-
-
-class ServerTest(Test):
-
-  def testKeepalive(self):
-    """ Verify that idle frames are sent to keep a Connection alive
-    """
-    idle_timeout = self.delay
-    server = common.TestServer()
-    server.start()
-
-    class Program:
-
-      def on_reactor_init(self, event):
-        self.conn = event.reactor.connection()
-        self.conn.hostname = "%s:%s" % (server.host, server.port)
-        self.conn.open()
-        self.old_count = None
-        event.reactor.schedule(3 * idle_timeout, self)
-
-      def on_connection_bound(self, event):
-        event.transport.idle_timeout = idle_timeout
-
-      def on_connection_remote_open(self, event):
-        self.old_count = event.transport.frames_input
-
-      def on_timer_task(self, event):
-        assert self.conn.state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE), "Connection terminated"
-        assert self.conn.transport.frames_input > self.old_count, "No idle frames received"
-        self.conn.close()
-
-    Reactor(Program()).run()
-    server.stop()
-
-  def testIdleTimeout(self):
-    """ Verify that a Connection is terminated properly when Idle frames do not
-    arrive in a timely manner.
-    """
-    idle_timeout = self.delay
-    server = common.TestServer(idle_timeout=idle_timeout)
-    server.start()
-
-    class Program:
-
-      def on_reactor_init(self, event):
-        self.conn = event.reactor.connection()
-        self.conn.hostname = "%s:%s" % (server.host, server.port)
-        self.conn.open()
-        self.remote_condition = None
-        self.old_count = None
-        # verify the connection stays up even if we don't explicitly send stuff
-        # wait up to 3x the idle timeout
-        event.reactor.schedule(3 * idle_timeout, self)
-
-      def on_connection_bound(self, event):
-        self.transport = event.transport
-
-      def on_connection_remote_open(self, event):
-        self.old_count = event.transport.frames_output
-
-      def on_connection_remote_close(self, event):
-        assert self.conn.remote_condition
-        assert self.conn.remote_condition.name == "amqp:resource-limit-exceeded"
-        self.remote_condition = self.conn.remote_condition
-
-      def on_timer_task(self, event):
-        assert self.conn.state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE), "Connection terminated"
-        assert self.conn.transport.frames_output > self.old_count, "No idle frames sent"
-
-        # now wait to explicitly cause the other side to expire:
-        suspend_time = 3 * idle_timeout
-        if os.name=="nt":
-          # On windows, the full delay gets too close to the graceful/hard close tipping point
-          suspend_time = 2.5 * idle_timeout
-        sleep(suspend_time)
-
-    p = Program()
-    Reactor(p).run()
-    assert p.remote_condition
-    assert p.remote_condition.name == "amqp:resource-limit-exceeded"
-    server.stop()
-
-class NoValue:
-
-  def __init__(self):
-    pass
-
-  def apply(self, dlv):
-    pass
-
-  def check(self, dlv):
-    assert dlv.data == None
-    assert dlv.section_number == 0
-    assert dlv.section_offset == 0
-    assert dlv.condition == None
-    assert dlv.failed == False
-    assert dlv.undeliverable == False
-    assert dlv.annotations == None
-
-class RejectValue:
-  def __init__(self, condition):
-    self.condition = condition
-
-  def apply(self, dlv):
-    dlv.condition = self.condition
-
-  def check(self, dlv):
-    assert dlv.data == None, dlv.data
-    assert dlv.section_number == 0
-    assert dlv.section_offset == 0
-    assert dlv.condition == self.condition, (dlv.condition, self.condition)
-    assert dlv.failed == False
-    assert dlv.undeliverable == False
-    assert dlv.annotations == None
-
-class ReceivedValue:
-  def __init__(self, section_number, section_offset):
-    self.section_number = section_number
-    self.section_offset = section_offset
-
-  def apply(self, dlv):
-    dlv.section_number = self.section_number
-    dlv.section_offset = self.section_offset
-
-  def check(self, dlv):
-    assert dlv.data == None, dlv.data
-    assert dlv.section_number == self.section_number, (dlv.section_number, self.section_number)
-    assert dlv.section_offset == self.section_offset
-    assert dlv.condition == None
-    assert dlv.failed == False
-    assert dlv.undeliverable == False
-    assert dlv.annotations == None
-
-class ModifiedValue:
-  def __init__(self, failed, undeliverable, annotations):
-    self.failed = failed
-    self.undeliverable = undeliverable
-    self.annotations = annotations
-
-  def apply(self, dlv):
-    dlv.failed = self.failed
-    dlv.undeliverable = self.undeliverable
-    dlv.annotations = self.annotations
-
-  def check(self, dlv):
-    assert dlv.data == None, dlv.data
-    assert dlv.section_number == 0
-    assert dlv.section_offset == 0
-    assert dlv.condition == None
-    assert dlv.failed == self.failed
-    assert dlv.undeliverable == self.undeliverable
-    assert dlv.annotations == self.annotations, (dlv.annotations, self.annotations)
-
-class CustomValue:
-  def __init__(self, data):
-    self.data = data
-
-  def apply(self, dlv):
-    dlv.data = self.data
-
-  def check(self, dlv):
-    assert dlv.data == self.data, (dlv.data, self.data)
-    assert dlv.section_number == 0
-    assert dlv.section_offset == 0
-    assert dlv.condition == None
-    assert dlv.failed == False
-    assert dlv.undeliverable == False
-    assert dlv.annotations == None
-
-class DeliveryTest(Test):
-
-  def tearDown(self):
-    self.cleanup()
-
-  def testDisposition(self, count=1, tag="tag%i", type=Delivery.ACCEPTED, value=NoValue()):
-    snd, rcv = self.link("test-link")
-    snd.open()
-    rcv.open()
-
-    snd_deliveries = []
-    for i in range(count):
-      d = snd.delivery(tag % i)
-      snd_deliveries.append(d)
-      snd.advance()
-
-    rcv.flow(count)
-    self.pump()
-
-    rcv_deliveries = []
-    for i in range(count):
-      d = rcv.current
-      assert d.tag == (tag % i)
-      rcv_deliveries.append(d)
-      rcv.advance()
-
-    for d in rcv_deliveries:
-      value.apply(d.local)
-      d.update(type)
-
-    self.pump()
-
-    for d in snd_deliveries:
-      assert d.remote_state == type
-      assert d.remote.type == type
-      value.check(d.remote)
-      value.apply(d.local)
-      d.update(type)
-
-    self.pump()
-
-    for d in rcv_deliveries:
-      assert d.remote_state == type
-      assert d.remote.type == type
-      value.check(d.remote)
-
-    for d in snd_deliveries:
-      d.settle()
-
-    self.pump()
-
-    for d in rcv_deliveries:
-      assert d.settled, d.settled
-      d.settle()
-
-  def testReceived(self):
-    self.testDisposition(type=Disposition.RECEIVED, value=ReceivedValue(1, 2))
-
-  def testRejected(self):
-    self.testDisposition(type=Disposition.REJECTED, value=RejectValue(Condition(symbol("foo"))))
-
-  def testReleased(self):
-    self.testDisposition(type=Disposition.RELEASED)
-
-  def testModified(self):
-    self.testDisposition(type=Disposition.MODIFIED,
-                         value=ModifiedValue(failed=True, undeliverable=True,
-                                             annotations={"key": "value"}))
-
-  def testCustom(self):
-    self.testDisposition(type=0x12345, value=CustomValue([1, 2, 3]))
-
-class CollectorTest(Test):
-
-  def setUp(self):
-    self.collector = Collector()
-
-  def drain(self):
-    result = []
-    while True:
-      e = self.collector.peek()
-      if e:
-        result.append(e)
-        self.collector.pop()
-      else:
-        break
-    return result
-
-  def expect(self, *types):
-    return self.expect_oneof(types)
-
-  def expect_oneof(self, *sequences):
-    events = self.drain()
-    types = tuple([e.type for e in events])
-
-    for alternative in sequences:
-      if types == alternative:
-        if len(events) == 1:
-          return events[0]
-        elif len(events) > 1:
-          return events
-        else:
-          return
-
-    assert False, "actual events %s did not match any of the expected sequences: %s" % (events, sequences)
-
-  def expect_until(self, *types):
-    events = self.drain()
-    etypes = tuple([e.type for e in events[-len(types):]])
-    assert etypes == types, "actual events %s did not end in expect sequence: %s" % (events, types)
-
-class EventTest(CollectorTest):
-
-  def tearDown(self):
-    self.cleanup()
-
-  def testEndpointEvents(self):
-    c1, c2 = self.connection()
-    c1.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    self.pump()
-    self.expect()
-    c2.open()
-    self.pump()
-    self.expect(Event.CONNECTION_REMOTE_OPEN)
-    self.pump()
-    self.expect()
-
-    ssn = c2.session()
-    snd = ssn.sender("sender")
-    ssn.open()
-    snd.open()
-
-    self.expect()
-    self.pump()
-    self.expect(Event.SESSION_INIT, Event.SESSION_REMOTE_OPEN,
-                Event.LINK_INIT, Event.LINK_REMOTE_OPEN)
-
-    c1.open()
-    ssn2 = c1.session()
-    ssn2.open()
-    rcv = ssn2.receiver("receiver")
-    rcv.open()
-    self.pump()
-    self.expect(Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.SESSION_INIT, Event.SESSION_LOCAL_OPEN,
-                Event.TRANSPORT, Event.LINK_INIT, Event.LINK_LOCAL_OPEN,
-                Event.TRANSPORT)
-
-    rcv.close()
-    self.expect(Event.LINK_LOCAL_CLOSE, Event.TRANSPORT)
-    self.pump()
-    rcv.free()
-    del rcv
-    self.expect(Event.LINK_FINAL)
-    ssn2.free()
-    del ssn2
-    self.pump()
-    c1.free()
-    c1.transport.unbind()
-    self.expect_oneof((Event.SESSION_FINAL, Event.LINK_FINAL, Event.SESSION_FINAL,
-                       Event.CONNECTION_UNBOUND, Event.CONNECTION_FINAL),
-                      (Event.CONNECTION_UNBOUND, Event.SESSION_FINAL, Event.LINK_FINAL,
-                       Event.SESSION_FINAL, Event.CONNECTION_FINAL))
-
-  def testConnectionINIT_FINAL(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    c.free()
-    self.expect(Event.CONNECTION_FINAL)
-
-  def testSessionINIT_FINAL(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    s = c.session()
-    self.expect(Event.SESSION_INIT)
-    s.free()
-    self.expect(Event.SESSION_FINAL)
-    c.free()
-    self.expect(Event.CONNECTION_FINAL)
-
-  def testLinkINIT_FINAL(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    s = c.session()
-    self.expect(Event.SESSION_INIT)
-    r = s.receiver("asdf")
-    self.expect(Event.LINK_INIT)
-    r.free()
-    self.expect(Event.LINK_FINAL)
-    c.free()
-    self.expect(Event.SESSION_FINAL, Event.CONNECTION_FINAL)
-
-  def testFlowEvents(self):
-    snd, rcv = self.link("test-link")
-    snd.session.connection.collect(self.collector)
-    rcv.open()
-    rcv.flow(10)
-    self.pump()
-    self.expect(Event.CONNECTION_INIT, Event.SESSION_INIT,
-                Event.LINK_INIT, Event.LINK_REMOTE_OPEN, Event.LINK_FLOW)
-    rcv.flow(10)
-    self.pump()
-    self.expect(Event.LINK_FLOW)
-    return snd, rcv
-
-  def testDeliveryEvents(self):
-    snd, rcv = self.link("test-link")
-    rcv.session.connection.collect(self.collector)
-    rcv.open()
-    rcv.flow(10)
-    self.pump()
-    self.expect(Event.CONNECTION_INIT, Event.SESSION_INIT,
-                Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
-    snd.delivery("delivery")
-    snd.send(b"Hello World!")
-    snd.advance()
-    self.pump()
-    self.expect()
-    snd.open()
-    self.pump()
-    self.expect(Event.LINK_REMOTE_OPEN, Event.DELIVERY)
-    rcv.session.connection.transport.unbind()
-    rcv.session.connection.free()
-    self.expect(Event.CONNECTION_UNBOUND, Event.TRANSPORT, Event.LINK_FINAL,
-                Event.SESSION_FINAL, Event.CONNECTION_FINAL)
-
-  def testDeliveryEventsDisp(self):
-    snd, rcv = self.testFlowEvents()
-    snd.open()
-    dlv = snd.delivery("delivery")
-    snd.send(b"Hello World!")
-    assert snd.advance()
-    self.expect(Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
-    self.pump()
-    self.expect(Event.LINK_FLOW)
-    rdlv = rcv.current
-    assert rdlv != None
-    assert rdlv.tag == "delivery"
-    rdlv.update(Delivery.ACCEPTED)
-    self.pump()
-    event = self.expect(Event.DELIVERY)
-    assert event.context == dlv, (dlv, event.context)
-
-  def testConnectionBOUND_UNBOUND(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    t = Transport()
-    t.bind(c)
-    self.expect(Event.CONNECTION_BOUND)
-    t.unbind()
-    self.expect(Event.CONNECTION_UNBOUND, Event.TRANSPORT)
-
-  def testTransportERROR_CLOSE(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    t = Transport()
-    t.bind(c)
-    self.expect(Event.CONNECTION_BOUND)
-    assert t.condition is None
-    t.push(b"asdf")
-    self.expect(Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED)
-    assert t.condition is not None
-    assert t.condition.name == "amqp:connection:framing-error"
-    assert "AMQP header mismatch" in t.condition.description
-    p = t.pending()
-    assert p > 0
-    t.pop(p)
-    self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testTransportCLOSED(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    t = Transport()
-    t.bind(c)
-    c.open()
-
-    self.expect(Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT)
-
-    c2 = Connection()
-    t2 = Transport()
-    t2.bind(c2)
-    c2.open()
-    c2.close()
-
-    pump(t, t2)
-
-    self.expect(Event.CONNECTION_REMOTE_OPEN, Event.CONNECTION_REMOTE_CLOSE,
-                Event.TRANSPORT_TAIL_CLOSED)
-
-    c.close()
-
-    pump(t, t2)
-
-    self.expect(Event.CONNECTION_LOCAL_CLOSE, Event.TRANSPORT,
-                Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testLinkDetach(self):
-    c1 = Connection()
-    c1.collect(self.collector)
-    t1 = Transport()
-    t1.bind(c1)
-    c1.open()
-    s1 = c1.session()
-    s1.open()
-    l1 = s1.sender("asdf")
-    l1.open()
-    l1.detach()
-    self.expect_until(Event.LINK_LOCAL_DETACH, Event.TRANSPORT)
-
-    c2 = Connection()
-    c2.collect(self.collector)
-    t2 = Transport()
-    t2.bind(c2)
-
-    pump(t1, t2)
-
-    self.expect_until(Event.LINK_REMOTE_DETACH)
-
-class PeerTest(CollectorTest):
-
-  def setUp(self):
-    CollectorTest.setUp(self)
-    self.connection = Connection()
-    self.connection.collect(self.collector)
-    self.transport = Transport()
-    self.transport.bind(self.connection)
-    self.peer = Connection()
-    self.peer_transport = Transport()
-    self.peer_transport.bind(self.peer)
-    self.peer_transport.trace(Transport.TRACE_OFF)
-
-  def pump(self):
-    pump(self.transport, self.peer_transport)
-
-class TeardownLeakTest(PeerTest):
-
-  def doLeak(self, local, remote):
-    self.connection.open()
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT)
-
-    ssn = self.connection.session()
-    ssn.open()
-    self.expect(Event.SESSION_INIT, Event.SESSION_LOCAL_OPEN, Event.TRANSPORT)
-
-    snd = ssn.sender("sender")
-    snd.open()
-    self.expect(Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
-
-
-    self.pump()
-
-    self.peer.open()
-    self.peer.session_head(0).open()
-    self.peer.link_head(0).open()
-
-    self.pump()
-    self.expect_oneof((Event.CONNECTION_REMOTE_OPEN, Event.SESSION_REMOTE_OPEN,
-                       Event.LINK_REMOTE_OPEN, Event.LINK_FLOW),
-                      (Event.CONNECTION_REMOTE_OPEN, Event.SESSION_REMOTE_OPEN,
-                       Event.LINK_REMOTE_OPEN))
-
-    if local:
-      snd.close() # ha!!
-      self.expect(Event.LINK_LOCAL_CLOSE, Event.TRANSPORT)
-    ssn.close()
-    self.expect(Event.SESSION_LOCAL_CLOSE, Event.TRANSPORT)
-    self.connection.close()
-    self.expect(Event.CONNECTION_LOCAL_CLOSE, Event.TRANSPORT)
-
-    if remote:
-      self.peer.link_head(0).close() # ha!!
-    self.peer.session_head(0).close()
-    self.peer.close()
-
-    self.pump()
-
-    if remote:
-      self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.LINK_REMOTE_CLOSE,
-                  Event.SESSION_REMOTE_CLOSE, Event.CONNECTION_REMOTE_CLOSE,
-                  Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_CLOSED)
-    else:
-      self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.SESSION_REMOTE_CLOSE,
-                  Event.CONNECTION_REMOTE_CLOSE, Event.TRANSPORT_TAIL_CLOSED,
-                  Event.TRANSPORT_CLOSED)
-
-    self.connection.free()
-    self.expect(Event.LINK_FINAL, Event.SESSION_FINAL)
-    self.transport.unbind()
-
-    self.expect(Event.CONNECTION_UNBOUND, Event.CONNECTION_FINAL)
-
-  def testLocalRemoteLeak(self):
-    self.doLeak(True, True)
-
-  def testLocalLeak(self):
-    self.doLeak(True, False)
-
-  def testRemoteLeak(self):
-    self.doLeak(False, True)
-
-  def testLeak(self):
-    self.doLeak(False, False)
-
-class IdleTimeoutEventTest(PeerTest):
-
-  def half_pump(self):
-    p = self.transport.pending()
-    if p>0:
-      self.transport.pop(p)
-
-  def testTimeoutWithZombieServer(self, expectOpenCloseFrames=True):
-    self.transport.idle_timeout = self.delay
-    self.connection.open()
-    self.half_pump()
-    t = time()
-    self.transport.tick(t)
-    self.transport.tick(t + self.delay*4)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED)
-    assert self.transport.capacity() < 0
-    if expectOpenCloseFrames:
-      assert self.transport.pending() > 0
-    self.half_pump()
-    self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-    assert self.transport.pending() < 0
-
-  def testTimeoutWithZombieServerAndSASL(self):
-    sasl = self.transport.sasl()
-    self.testTimeoutWithZombieServer(expectOpenCloseFrames=False)
-
-class DeliverySegFaultTest(Test):
-
-  def testDeliveryAfterUnbind(self):
-    conn = Connection()
-    t = Transport()
-    ssn = conn.session()
-    snd = ssn.sender("sender")
-    dlv = snd.delivery("tag")
-    dlv.settle()
-    del dlv
-    t.bind(conn)
-    t.unbind()
-    dlv = snd.delivery("tag")
-
-class SaslEventTest(CollectorTest):
-
-  def testAnonymousNoInitialResponse(self):
-    conn = Connection()
-    conn.collect(self.collector)
-    transport = Transport(Transport.SERVER)
-    transport.bind(conn)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
-
-    transport.push(b'AMQP\x03\x01\x00\x00\x00\x00\x00 \x02\x01\x00\x00\x00SA'
-                   b'\xd0\x00\x00\x00\x10\x00\x00\x00\x02\xa3\tANONYMOUS@'
-                   b'AMQP\x00\x01\x00\x00')
-    self.expect(Event.TRANSPORT)
-    for i in range(1024):
-      p = transport.pending()
-      self.drain()
-    p = transport.pending()
-    self.expect()
-
-  def testPipelinedServerReadFirst(self):
-    conn = Connection()
-    conn.collect(self.collector)
-    transport = Transport(Transport.CLIENT)
-    s = transport.sasl()
-    s.allowed_mechs("ANONYMOUS PLAIN")
-    transport.bind(conn)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
-    transport.push(
-        # SASL
-        b'AMQP\x03\x01\x00\x00'
-        # @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:ANONYMOUS]]
-        b'\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS'
-        # @sasl-outcome(68) [code=0]
-        b'\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00'
-        # AMQP
-        b'AMQP\x00\x01\x00\x00'
-        )
-    self.expect(Event.TRANSPORT)
-    p = transport.pending()
-    bytes = transport.peek(p)
-    transport.pop(p)
-
-    server = Transport(Transport.SERVER)
-    server.push(bytes)
-    assert s.outcome == SASL.OK
-    assert server.sasl().outcome == SASL.OK
-
-  def testPipelinedServerWriteFirst(self):
-    conn = Connection()
-    conn.collect(self.collector)
-    transport = Transport(Transport.CLIENT)
-    s = transport.sasl()
-    s.allowed_mechs("ANONYMOUS")
-    transport.bind(conn)
-    p = transport.pending()
-    bytes = transport.peek(p)
-    transport.pop(p)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
-    transport.push(
-        # SASL
-        b'AMQP\x03\x01\x00\x00'
-        # @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:ANONYMOUS]]
-        b'\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS'
-        # @sasl-outcome(68) [code=0]
-        b'\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00'
-        # AMQP
-        b'AMQP\x00\x01\x00\x00'
-        )
-    self.expect(Event.TRANSPORT)
-    p = transport.pending()
-    bytes = transport.peek(p)
-    transport.pop(p)
-    assert s.outcome == SASL.OK
-    # XXX: the bytes above appear to be correct, but we don't get any
-    # sort of event indicating that the transport is authenticated

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/handler.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/handler.py b/tests/python/proton_tests/handler.py
deleted file mode 100644
index c7210f4..0000000
--- a/tests/python/proton_tests/handler.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-from __future__ import absolute_import
-
-import os, gc, traceback
-import sys
-from . import common
-from time import time, sleep
-from proton import *
-from .common import pump, Skipped
-from proton.reactor import Reactor
-
-
-CUSTOM = EventType("custom")
-
-class HandlerTest(common.Test):
-  def test_reactorHandlerCycling(self, n=0):
-
-    class CustomHandler(Handler):
-      UNSET = 999999999
-      def __init__(self):
-        self.offset = len(traceback.extract_stack())
-      def on_reactor_init(self, event):
-        self.depth = len(traceback.extract_stack())
-      def reset(self):
-        self.depth = self.UNSET
-      @property
-      def init_depth(self):
-        d = self.depth - self.offset
-        return d
-    custom = CustomHandler()
-
-    reactor = Reactor()
-    reactor.handler = custom
-    for i in range(n):
-      h = reactor.handler
-      reactor.handler = h
-    custom.reset()
-    reactor.run()
-    assert custom.init_depth < 50, "Unexpectedly long traceback for a simple handler"
-
-  def test_reactorHandlerCycling10k(self):
-    self.test_reactorHandlerCycling(10000)
-
-  def test_reactorHandlerCycling100(self):
-    self.test_reactorHandlerCycling(100)
-
-  def do_customEvent(self, reactor_handler, event_root):
-
-    class CustomHandler:
-      did_custom = False
-      did_init = False
-      def __init__(self, *handlers):
-        self.handlers = handlers
-      def on_reactor_init(self, event):
-        self.did_init = True
-      def on_custom(self, event):
-        self.did_custom = True
-
-    class CustomInvoker(CustomHandler):
-      def on_reactor_init(self, event):
-        h = event_root(event)
-        event.dispatch(h, CUSTOM)
-        self.did_init = True
-
-    child = CustomInvoker()
-    root = CustomHandler(child)
-
-    reactor = Reactor()
-
-    reactor_handler(reactor, root)
-    reactor.run()
-    assert root.did_init
-    assert child.did_init
-    assert root.did_custom
-    assert child.did_custom
-    
-  def set_root(self, reactor, root):
-    reactor.handler = root
-  def add_root(self, reactor, root):
-    reactor.handler.add(root)
-  def append_root(self, reactor, root):
-    reactor.handler.handlers.append(root)
-    
-  def event_root(self, event):
-    return event.root
-  
-  def event_reactor_handler(self, event):
-    return event.reactor.handler
-
-  def test_set_handler(self):
-    self.do_customEvent(self.set_root, self.event_reactor_handler)
-
-  def test_add_handler(self):
-    self.do_customEvent(self.add_root, self.event_reactor_handler)
-
-  def test_append_handler(self):
-    self.do_customEvent(self.append_root, self.event_reactor_handler)
-
-  def test_set_root(self):
-    self.do_customEvent(self.set_root, self.event_root)
-
-  def test_add_root(self):
-    self.do_customEvent(self.add_root, self.event_root)
-
-  def test_append_root(self):
-    self.do_customEvent(self.append_root, self.event_root)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[11/11] qpid-proton git commit: PROTON-1885: [python] move tests/python to python/tests

Posted by ac...@apache.org.
PROTON-1885: [python] move tests/python to python/tests

Consistent with other bindings


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/9778eda8
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/9778eda8
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/9778eda8

Branch: refs/heads/master
Commit: 9778eda8e9387caa8a207fbb6fedfa09ac0e298a
Parents: b41f60d
Author: Alan Conway <ac...@redhat.com>
Authored: Wed Jul 4 14:52:06 2018 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Fri Jul 6 12:20:32 2018 -0400

----------------------------------------------------------------------
 CMakeLists.txt                                  |   64 -
 misc/config.sh.in                               |    4 +-
 misc/tox.ini.in                                 |   26 -
 python/CMakeLists.txt                           |   59 +
 python/tests/interop-generate                   |  150 +
 python/tests/proton-test                        |  711 +++++
 python/tests/proton_tests/__init__.py           |   31 +
 python/tests/proton_tests/codec.py              |  401 +++
 python/tests/proton_tests/common.py             |  510 ++++
 python/tests/proton_tests/engine.py             | 2714 ++++++++++++++++++
 python/tests/proton_tests/handler.py            |  123 +
 python/tests/proton_tests/interop.py            |  147 +
 python/tests/proton_tests/message.py            |  275 ++
 python/tests/proton_tests/reactor.py            |  485 ++++
 python/tests/proton_tests/sasl.py               |  587 ++++
 python/tests/proton_tests/soak.py               |  334 +++
 python/tests/proton_tests/ssl.py                |  936 ++++++
 python/tests/proton_tests/ssl_db/README.txt     |   79 +
 .../ssl_db/bad-server-certificate.p12           |  Bin 0 -> 1490 bytes
 .../ssl_db/bad-server-certificate.pem           |   22 +
 .../ssl_db/bad-server-private-key.pem           |   15 +
 .../tests/proton_tests/ssl_db/bad-server.pkcs12 |  Bin 0 -> 1524 bytes
 .../proton_tests/ssl_db/ca-certificate.p12      |  Bin 0 -> 992 bytes
 .../proton_tests/ssl_db/ca-certificate.pem      |   24 +
 python/tests/proton_tests/ssl_db/ca.pkcs12      |  Bin 0 -> 1572 bytes
 .../proton_tests/ssl_db/client-certificate.p12  |  Bin 0 -> 1546 bytes
 .../proton_tests/ssl_db/client-certificate.pem  |   18 +
 .../proton_tests/ssl_db/client-certificate1.p12 |  Bin 0 -> 1604 bytes
 .../proton_tests/ssl_db/client-certificate1.pem |   19 +
 .../proton_tests/ssl_db/client-private-key.pem  |   15 +
 .../proton_tests/ssl_db/client-private-key1.pem |   15 +
 .../proton_tests/ssl_db/client-request.pem      |   15 +
 .../proton_tests/ssl_db/client-request1.pem     |   16 +
 python/tests/proton_tests/ssl_db/client.pkcs12  |  Bin 0 -> 1532 bytes
 python/tests/proton_tests/ssl_db/client1.pkcs12 |  Bin 0 -> 1646 bytes
 .../proton_tests/ssl_db/server-certificate.p12  |  Bin 0 -> 1562 bytes
 .../proton_tests/ssl_db/server-certificate.pem  |   18 +
 .../proton_tests/ssl_db/server-private-key.pem  |   15 +
 .../proton_tests/ssl_db/server-request.pem      |   15 +
 .../ssl_db/server-wc-certificate.p12            |  Bin 0 -> 1624 bytes
 .../ssl_db/server-wc-certificate.pem            |   19 +
 .../ssl_db/server-wc-private-key.pem            |   15 +
 .../proton_tests/ssl_db/server-wc-request.pem   |   16 +
 .../tests/proton_tests/ssl_db/server-wc.pkcs12  |  Bin 0 -> 1626 bytes
 python/tests/proton_tests/ssl_db/server.pkcs12  |  Bin 0 -> 1572 bytes
 python/tests/proton_tests/transport.py          |  393 +++
 python/tests/proton_tests/url.py                |  147 +
 python/tests/proton_tests/utils.py              |  163 ++
 python/tests/tox-blacklist                      |   12 +
 python/tox.ini.in                               |   26 +
 scripts/jenkins-proton-c-build.sh               |    2 +-
 tests/python/interop-generate                   |  150 -
 tests/python/proton-test                        |  711 -----
 tests/python/proton_tests/__init__.py           |   31 -
 tests/python/proton_tests/codec.py              |  401 ---
 tests/python/proton_tests/common.py             |  510 ----
 tests/python/proton_tests/engine.py             | 2714 ------------------
 tests/python/proton_tests/handler.py            |  123 -
 tests/python/proton_tests/interop.py            |  147 -
 tests/python/proton_tests/message.py            |  275 --
 tests/python/proton_tests/reactor.py            |  485 ----
 tests/python/proton_tests/sasl.py               |  587 ----
 tests/python/proton_tests/soak.py               |  334 ---
 tests/python/proton_tests/ssl.py                |  936 ------
 tests/python/proton_tests/ssl_db/README.txt     |   79 -
 .../ssl_db/bad-server-certificate.p12           |  Bin 1490 -> 0 bytes
 .../ssl_db/bad-server-certificate.pem           |   22 -
 .../ssl_db/bad-server-private-key.pem           |   15 -
 .../proton_tests/ssl_db/bad-server.pkcs12       |  Bin 1524 -> 0 bytes
 .../proton_tests/ssl_db/ca-certificate.p12      |  Bin 992 -> 0 bytes
 .../proton_tests/ssl_db/ca-certificate.pem      |   24 -
 tests/python/proton_tests/ssl_db/ca.pkcs12      |  Bin 1572 -> 0 bytes
 .../proton_tests/ssl_db/client-certificate.p12  |  Bin 1546 -> 0 bytes
 .../proton_tests/ssl_db/client-certificate.pem  |   18 -
 .../proton_tests/ssl_db/client-certificate1.p12 |  Bin 1604 -> 0 bytes
 .../proton_tests/ssl_db/client-certificate1.pem |   19 -
 .../proton_tests/ssl_db/client-private-key.pem  |   15 -
 .../proton_tests/ssl_db/client-private-key1.pem |   15 -
 .../proton_tests/ssl_db/client-request.pem      |   15 -
 .../proton_tests/ssl_db/client-request1.pem     |   16 -
 tests/python/proton_tests/ssl_db/client.pkcs12  |  Bin 1532 -> 0 bytes
 tests/python/proton_tests/ssl_db/client1.pkcs12 |  Bin 1646 -> 0 bytes
 .../proton_tests/ssl_db/server-certificate.p12  |  Bin 1562 -> 0 bytes
 .../proton_tests/ssl_db/server-certificate.pem  |   18 -
 .../proton_tests/ssl_db/server-private-key.pem  |   15 -
 .../proton_tests/ssl_db/server-request.pem      |   15 -
 .../ssl_db/server-wc-certificate.p12            |  Bin 1624 -> 0 bytes
 .../ssl_db/server-wc-certificate.pem            |   19 -
 .../ssl_db/server-wc-private-key.pem            |   15 -
 .../proton_tests/ssl_db/server-wc-request.pem   |   16 -
 .../python/proton_tests/ssl_db/server-wc.pkcs12 |  Bin 1626 -> 0 bytes
 tests/python/proton_tests/ssl_db/server.pkcs12  |  Bin 1572 -> 0 bytes
 tests/python/proton_tests/transport.py          |  393 ---
 tests/python/proton_tests/url.py                |  147 -
 tests/python/proton_tests/utils.py              |  163 --
 tests/python/tox-blacklist                      |   13 -
 96 files changed, 8543 insertions(+), 8549 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c2f17c9..b7ea06c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -134,9 +134,6 @@ endif()
 
 message(STATUS "PN_VERSION: ${PN_VERSION} (${PN_VERSION_QUALIFIER})")
 
-set (pn_test_root "${CMAKE_CURRENT_SOURCE_DIR}/tests")
-set (pn_test_bin "${CMAKE_CURRENT_BINARY_DIR}/tests")
-
 # In rpm builds the build sets some variables:
 #  CMAKE_INSTALL_PREFIX - this is a standard cmake variable
 #  INCLUDE_INSTALL_DIR
@@ -343,67 +340,6 @@ endforeach(BINDING)
 
 unset(BUILD_BINDINGS CACHE) # Remove from cache, only relevant when creating the initial cache.
 
-# python test: tests/python/proton-test
-if (BUILD_PYTHON)
-  set (py_root "${pn_test_root}/python")
-  set (py_src "${CMAKE_CURRENT_SOURCE_DIR}/python")
-  set (py_bin "${CMAKE_CURRENT_BINARY_DIR}/python")
-  set (py_dll "$<TARGET_FILE_DIR:_cproton>")
-  set (py_bld "$<TARGET_FILE_DIR:qpid-proton>") # For windows
-  set (app_path $<TARGET_FILE_DIR:msgr-send> "${pn_test_root}/tools/apps/python")
-  set (py_path ${py_bld} ${app_path} $ENV{PATH})
-  set (py_pythonpath ${py_root} ${py_src} ${py_bin} ${py_dll} $ENV{PYTHONPATH})
-  to_native_path ("${py_pythonpath}" py_pythonpath)
-  to_native_path ("${py_path}" py_path)
-
-  if (CMAKE_BUILD_TYPE MATCHES "Coverage")
-    set (python_coverage_options -m coverage run)
-  endif(CMAKE_BUILD_TYPE MATCHES "Coverage")
-
-  add_test (NAME python-test
-            COMMAND ${PN_ENV_SCRIPT}
-              "PATH=${py_path}" "PYTHONPATH=${py_pythonpath}"
-              "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
-              ${VALGRIND_ENV}
-              ${PYTHON_EXECUTABLE} -- ${python_coverage_options} "${py_root}/proton-test")
-  set_tests_properties(python-test PROPERTIES PASS_REGULAR_EXPRESSION "Totals: .* 0 failed")
-
-  check_python_module("tox" TOX_MODULE_FOUND)
-  if (NOT TOX_MODULE_FOUND)
-    message(STATUS "The tox tool is not available; skipping the python-tox-tests")
-  else ()
-    option(ENABLE_TOX_TEST "Enable multi-version python testing with TOX" ON)
-
-    set(tox_default "py26,py27,py34,py35,py36")
-    set(TOX_ENVLIST ${tox_default} CACHE STRING "List of python environments for TOX tests" )
-    mark_as_advanced(TOX_ENVLIST)
-
-    if (NOT (TOX_ENVLIST STREQUAL tox_default))
-      message(WARNING "non-default TOX test set '${TOX_ENVLIST}' (default '${tox_default}')")
-    endif()
-    if (ENABLE_TOX_TEST)
-      if (CMAKE_BUILD_TYPE MATCHES "Coverage")
-        message(STATUS "Building for coverage analysis; skipping the python-tox-tests")
-      else ()
-        configure_file(
-          "${CMAKE_CURRENT_SOURCE_DIR}/misc/tox.ini.in"
-          "${CMAKE_CURRENT_BINARY_DIR}/tox.ini")
-        add_test (NAME python-tox-test
-                  COMMAND ${PN_ENV_SCRIPT}
-                  "PATH=${py_path}"
-                  "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
-                  "SWIG=${SWIG_EXECUTABLE}"
-                  ${VALGRIND_ENV} --
-                  ${PYTHON_EXECUTABLE} -m tox)
-        set_tests_properties(python-tox-test
-                             PROPERTIES
-                               PASS_REGULAR_EXPRESSION "Totals: .* ignored, 0 failed"
-                               FAIL_REGULAR_EXPRESSION "ERROR:[ ]+py[0-9]*: commands failed")
-      endif ()
-    endif (ENABLE_TOX_TEST)
-  endif (NOT TOX_MODULE_FOUND)
-endif (BUILD_PYTHON)
-
 install (FILES LICENSE.txt README.md
          DESTINATION ${PROTON_SHARE})
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/misc/config.sh.in
----------------------------------------------------------------------
diff --git a/misc/config.sh.in b/misc/config.sh.in
old mode 100644
new mode 100755
index 8b3475f..a61c757
--- a/misc/config.sh.in
+++ b/misc/config.sh.in
@@ -34,7 +34,7 @@ PROTON_BUILD=@CMAKE_BINARY_DIR@
 PYTHON_BINDING=$PROTON_BUILD/python
 
 # Python
-COMMON_PYPATH=$PROTON_HOME/tests/python:$PROTON_HOME/python:$PROTON_HOME/tools/python
+COMMON_PYPATH=$PROTON_HOME/python/tests:$PROTON_HOME/python:$PROTON_HOME/tools/python
 export PYTHONPATH=$COMMON_PYPATH:$PYTHON_BINDING
 
 # Ruby
@@ -50,7 +50,7 @@ export LIBRARY_PATH="$(merge_paths $PROTON_BUILD $LIBRARY_PATH)"
 export LD_LIBRARY_PATH="$(merge_paths $PROTON_BUILD $LD_LIBRARY_PATH)"
 
 # Test applications
-export PATH="$(merge_paths $PATH $PROTON_BUILD/c/tools $PROTON_HOME/tests/python)"
+export PATH="$(merge_paths $PATH $PROTON_BUILD/c/tools $PROTON_HOME/python/tests)"
 
 # Can the test harness use valgrind?
 if [[ -x "$(type -p valgrind)" && "@ENABLE_VALGRIND@" == "ON" ]] ; then

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/misc/tox.ini.in
----------------------------------------------------------------------
diff --git a/misc/tox.ini.in b/misc/tox.ini.in
deleted file mode 100644
index 1000282..0000000
--- a/misc/tox.ini.in
+++ /dev/null
@@ -1,26 +0,0 @@
-[tox]
-envlist = @TOX_ENVLIST@
-minversion = 1.4
-skipdist = True
-setupdir = @py_bin@/dist
-
-[testenv]
-usedevelop = False
-setenv =
-    VIRTUAL_ENV={envdir}
-    DEBUG=True
-passenv =
-    PKG_CONFIG_PATH
-    CFLAGS
-    SASLPASSWD
-    VALGRIND
-commands =
-    @CMAKE_SOURCE_DIR@/tests/python/proton-test '{posargs:--ignore-file=@CMAKE_SOURCE_DIR@/tests/python/tox-blacklist}'
-deps =
-    unittest2
-
-[testenv:pep8]
-commands = flake8
-
-[testenv:docs]
-commands = python setup.py build_sphinx

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 037552e..31fcfba 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -184,3 +184,62 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README.rst.in
                ${py_dist_dir}/README.rst
 )
+
+# python test: python/tests/proton-test
+set (py_src "${CMAKE_CURRENT_SOURCE_DIR}")
+set (py_bin "${CMAKE_CURRENT_BINARY_DIR}")
+set (py_dll "$<TARGET_FILE_DIR:_cproton>")
+set (py_bld "$<TARGET_FILE_DIR:qpid-proton>") # For windows
+set (py_tests "${py_src}/tests")
+
+set (py_path ${CMAKE_BINARY_DIR}/c/tools ${py_bld} $ENV{PATH})
+set (py_pythonpath ${py_tests} ${py_src} ${py_bin} ${py_dll} $ENV{PYTHONPATH})
+to_native_path ("${py_pythonpath}" py_pythonpath)
+to_native_path ("${py_path}" py_path)
+
+if (CMAKE_BUILD_TYPE MATCHES "Coverage")
+  set (python_coverage_options -m coverage run)
+endif(CMAKE_BUILD_TYPE MATCHES "Coverage")
+
+add_test (NAME python-test
+  COMMAND ${PN_ENV_SCRIPT}
+  "PATH=${py_path}" "PYTHONPATH=${py_pythonpath}"
+  "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
+  ${VALGRIND_ENV}
+  ${PYTHON_EXECUTABLE} -- ${python_coverage_options} "${py_tests}/proton-test")
+set_tests_properties(python-test PROPERTIES PASS_REGULAR_EXPRESSION "Totals: .* 0 failed")
+
+check_python_module("tox" TOX_MODULE_FOUND)
+if (NOT TOX_MODULE_FOUND)
+  message(STATUS "The tox tool is not available; skipping the python-tox-tests")
+else ()
+  option(ENABLE_TOX_TEST "Enable multi-version python testing with TOX" ON)
+
+  set(tox_default "py26,py27,py34,py35,py36")
+  set(TOX_ENVLIST ${tox_default} CACHE STRING "List of python environments for TOX tests" )
+  mark_as_advanced(TOX_ENVLIST)
+
+  if (NOT (TOX_ENVLIST STREQUAL tox_default))
+    message(WARNING "non-default TOX test set '${TOX_ENVLIST}' (default '${tox_default}')")
+  endif()
+  if (ENABLE_TOX_TEST)
+    if (CMAKE_BUILD_TYPE MATCHES "Coverage")
+      message(STATUS "Building for coverage analysis; skipping the python-tox-tests")
+    else ()
+      configure_file(
+        "${CMAKE_CURRENT_SOURCE_DIR}/tox.ini.in"
+        "${CMAKE_CURRENT_BINARY_DIR}/tox.ini")
+      add_test (NAME python-tox-test
+        COMMAND ${PN_ENV_SCRIPT}
+        "PATH=${py_path}"
+        "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
+        "SWIG=${SWIG_EXECUTABLE}"
+        ${VALGRIND_ENV} --
+        ${PYTHON_EXECUTABLE} -m tox)
+      set_tests_properties(python-tox-test
+        PROPERTIES
+        PASS_REGULAR_EXPRESSION "Totals: .* ignored, 0 failed"
+        FAIL_REGULAR_EXPRESSION "ERROR:[ ]+py[0-9]*: commands failed")
+    endif ()
+  endif (ENABLE_TOX_TEST)
+endif (NOT TOX_MODULE_FOUND)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/interop-generate
----------------------------------------------------------------------
diff --git a/python/tests/interop-generate b/python/tests/interop-generate
new file mode 100755
index 0000000..9c360a6
--- /dev/null
+++ b/python/tests/interop-generate
@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+# Generate encoded  AMQP fragments for interop testing.
+
+import logging, optparse, os, struct, sys, time, traceback, types, cgi
+from proton import *
+
+def main(argv):
+
+    def write(data, filename):
+        f = open(filename+".amqp", 'w')
+        f.write(data.encode())
+        f.close()
+
+    # message
+    m = Message()
+    d = Data()
+    d.put_string("hello")
+    m.body = d.encode()
+    write(m, "message")
+
+    # null
+    d = Data()
+    d.put_null()
+    write(d, "null")
+
+    # primitive types
+    d = Data()
+    d.put_bool(True)
+    d.put_bool(False)
+    d.put_ubyte(42)
+    d.put_ushort(42)
+    d.put_short(-42)
+    d.put_uint(12345)
+    d.put_int(-12345)
+    d.put_ulong(12345)
+    d.put_long(-12345)
+    d.put_float(0.125)
+    d.put_double(0.125)
+    write(d, "primitives")
+
+    # string types
+    d = Data()
+    d.put_binary("abc\0defg")
+    d.put_string("abcdefg")
+    d.put_symbol("abcdefg")
+    d.put_binary("")
+    d.put_string("")
+    d.put_symbol("")
+    write(d, "strings")
+
+    # described types
+    d = Data()
+    d.put_described()
+    d.enter()
+    d.put_symbol("foo-descriptor")
+    d.put_string("foo-value")
+    d.exit()
+
+    d.put_described()
+    d.enter()
+    d.put_int(12)
+    d.put_int(13)
+    d.exit()
+
+    write(d, "described")
+
+    # described array
+    d = Data()
+    d.put_array(True, Data.INT)
+    d.enter()
+    d.put_symbol("int-array")
+    for i in xrange(0,10): d.put_int(i)
+    d.exit()
+    write(d, "described_array")
+
+
+    # Arrays
+
+    # Integer array
+    d = Data()
+    d.put_array(False, Data.INT)
+    d.enter()
+    for i in xrange(0,100): d.put_int(i)
+    d.exit()
+
+    # String array
+    d.put_array(False, Data.STRING)
+    d.enter()
+    for i in ["a", "b", "c"]: d.put_string(i)
+    d.exit()
+
+    # empty array
+    d.put_array(False, Data.INT)
+
+    write(d, "arrays")
+
+    # List - mixed types
+    d = Data()
+    d.put_list()
+    d.enter()
+    d.put_int(32)
+    d.put_string("foo")
+    d.put_bool(True)
+    d.exit()
+
+    d.put_list()                # Empty list
+    write(d, "lists")
+
+    # Maps
+    d = Data()
+    d.put_map()
+    d.enter()
+    for k,v in {"one":1, "two":2, "three":3}.items():
+        d.put_string(k)
+        d.put_int(v)
+    d.exit()
+
+    d.put_map()
+    d.enter()
+    for k,v in {1:"one", 2:"two", 3:"three"}.items():
+        d.put_int(k)
+        d.put_string(v)
+    d.exit()
+
+    d.put_map()                 # Empty map
+    write(d, "maps")
+
+    return 0
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv))

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton-test
----------------------------------------------------------------------
diff --git a/python/tests/proton-test b/python/tests/proton-test
new file mode 100755
index 0000000..6280556
--- /dev/null
+++ b/python/tests/proton-test
@@ -0,0 +1,711 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+# TODO: summarize, test harness preconditions (e.g. broker is alive)
+
+import logging, optparse, os, struct, sys, time, traceback, types, cgi
+from fnmatch import fnmatchcase as match
+from getopt import GetoptError
+from logging import getLogger, StreamHandler, Formatter, Filter, \
+    WARN, DEBUG, ERROR
+import unittest
+from proton_tests.common import SkipTest
+
+if sys.version_info[0] == 3:
+    CLASS_TYPES = (type,)
+else:
+    CLASS_TYPES = (type, types.ClassType)
+
+levels = {
+  "DEBUG": DEBUG,
+  "WARN": WARN,
+  "ERROR": ERROR
+  }
+
+sorted_levels = [(v, k) for k, v in list(levels.items())]
+sorted_levels.sort()
+sorted_levels = [v for k, v in sorted_levels]
+
+parser = optparse.OptionParser(usage="usage: %prog [options] PATTERN ...",
+                               description="Run tests matching the specified PATTERNs.")
+parser.add_option("-l", "--list", action="store_true", default=False,
+                  help="list tests instead of executing them")
+parser.add_option("-f", "--log-file", metavar="FILE", help="log output to FILE")
+parser.add_option("-v", "--log-level", metavar="LEVEL", default="WARN",
+                  help="only display log messages of LEVEL or higher severity: "
+                  "%s (default %%default)" % ", ".join(sorted_levels))
+parser.add_option("-c", "--log-category", metavar="CATEGORY", action="append",
+                  dest="log_categories", default=[],
+                  help="log only categories matching CATEGORY pattern")
+parser.add_option("-m", "--module", action="append", default=[],
+                  dest="modules", help="add module to test search path")
+parser.add_option("-i", "--ignore", action="append", default=[],
+                  help="ignore tests matching IGNORE pattern")
+parser.add_option("-I", "--ignore-file", metavar="IFILE", action="append",
+                  default=[],
+                  help="ignore tests matching patterns in IFILE")
+parser.add_option("-H", "--halt-on-error", action="store_true", default=False,
+                  dest="hoe", help="halt if an error is encountered")
+parser.add_option("-t", "--time", action="store_true", default=False,
+                  help="report timing information on test run")
+parser.add_option("-D", "--define", metavar="DEFINE", dest="defines",
+                  action="append", default=[], help="define test parameters")
+parser.add_option("-x", "--xml", metavar="XML", dest="xml",
+                  help="write test results in Junit style xml suitable for use by CI tools etc")
+parser.add_option("-a", "--always-colorize", action="store_true", dest="always_colorize", default=False,
+                  help="always colorize the test results rather than relying on terminal tty detection. Useful when invoked from Jython/Maven.")
+parser.add_option("-n", metavar="count", dest="count", type=int, default=1,
+                  help="run the tests <count> times")
+parser.add_option("-b", "--bare", action="store_true", default=False,
+                  help="Run bare, i.e. don't capture stack traces. This is useful under Jython as " +
+                  "captured stack traces do not include the Java portion of the stack," +
+                  "whereas non captured stack traces do.")
+parser.add_option("-j", "--javatrace", action="store_true", default=False,
+                  help="Show the full java stack trace. This disables heuristics to eliminate the " +
+                  "jython portion of java stack traces.")
+
+class Config:
+
+  def __init__(self):
+    self.defines = {}
+    self.log_file = None
+    self.log_level = WARN
+    self.log_categories = []
+
+opts, args = parser.parse_args()
+
+# Known bad tests, skipped unless specifically matched on the command line
+known_bad = ["proton_tests.messenger.*"]
+
+includes = []
+excludes = ["*__*__"]
+config = Config()
+list_only = opts.list
+for d in opts.defines:
+  try:
+    idx = d.index("=")
+    name = d[:idx]
+    value = d[idx+1:]
+    config.defines[name] = value
+  except ValueError:
+    config.defines[d] = None
+config.log_file = opts.log_file
+config.log_level = levels[opts.log_level.upper()]
+config.log_categories = opts.log_categories
+excludes.extend([v.strip() for v in opts.ignore])
+for v in opts.ignore_file:
+  f = open(v)
+  for line in f:
+    line = line.strip()
+    if line.startswith("#"):
+      continue
+    excludes.append(line)
+  f.close()
+
+for a in args:
+  includes.append(a.strip())
+
+def is_ignored(path):
+  for p in excludes:
+    if match(path, p):
+      return True
+  return False
+
+def is_included(path):
+  if is_ignored(path):
+    return False
+  for p in includes:
+    if match(path, p):
+      return True
+  for p in known_bad:
+    if match(path, p):
+      return False
+  return not includes           # If includes is empty, include everything
+
+def is_smart():
+  return sys.stdout.isatty() and os.environ.get("TERM", "dumb") != "dumb"
+
+try:
+  import fcntl, termios
+
+  def width():
+    if is_smart():
+      s = struct.pack("HHHH", 0, 0, 0, 0)
+      fd_stdout = sys.stdout.fileno()
+      x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s)
+      rows, cols, xpx, ypx = struct.unpack("HHHH", x)
+      return cols
+    else:
+      try:
+        return int(os.environ.get("COLUMNS", "80"))
+      except ValueError:
+        return 80
+
+  WIDTH = width()
+
+  def resize(sig, frm):
+    global WIDTH
+    WIDTH = width()
+
+  import signal
+  signal.signal(signal.SIGWINCH, resize)
+
+except ImportError:
+  WIDTH = 80
+
+def vt100_attrs(*attrs):
+  return "\x1B[%sm" % ";".join(map(str, attrs))
+
+vt100_reset = vt100_attrs(0)
+
+KEYWORDS = {"pass": (32,),
+            "skip": (33,),
+            "fail": (31,),
+            "start": (34,),
+            "total": (34,),
+            "ignored": (33,),
+            "selected": (34,),
+            "elapsed": (34,),
+            "average": (34,)}
+
+def colorize_word(word, text=None):
+  if text is None:
+    text = word
+  return colorize(text, *KEYWORDS.get(word, ()))
+
+def colorize(text, *attrs):
+  if attrs and (is_smart() or opts.always_colorize):
+    return "%s%s%s" % (vt100_attrs(*attrs), text, vt100_reset)
+  else:
+    return text
+
+def indent(text):
+  lines = text.split("\n")
+  return "  %s" % "\n  ".join(lines)
+
+# Write a 'minimal' Junit xml style report file suitable for use by CI tools such as Jenkins.
+class JunitXmlStyleReporter:
+
+  def __init__(self, file):
+    self.f = open(file, "w");
+
+  def begin(self):
+    self.f.write('<?xml version="1.0" encoding="UTF-8" ?>\n')
+    self.f.write('<testsuite name="pythontests">\n')
+
+  def report(self, name, result):
+    parts = name.split(".")
+    method = parts[-1]
+    module = '.'.join(parts[0:-1])
+    self.f.write('<testcase classname="%s" name="%s" time="%f">\n' % (module, method, result.time))
+    if result.failed:
+      escaped_type = cgi.escape(str(result.exception_type))
+      escaped_message = cgi.escape(str(result.exception_message))
+      self.f.write('<failure type="%s" message="%s">\n' % (escaped_type, escaped_message))
+      self.f.write('<![CDATA[\n')
+      self.f.write(result.formatted_exception_trace)
+      self.f.write(']]>\n')
+      self.f.write('</failure>\n')
+    if result.skipped:
+      self.f.write('<skipped/>\n')
+    self.f.write('</testcase>\n')
+
+  def end(self):
+      self.f.write('</testsuite>\n')
+      self.f.close()
+
+class Interceptor:
+
+  def __init__(self):
+    self.newline = False
+    self.indent = False
+    self.passthrough = True
+    self.dirty = False
+    self.last = None
+
+  def begin(self):
+    self.newline = True
+    self.indent = True
+    self.passthrough = False
+    self.dirty = False
+    self.last = None
+
+  def reset(self):
+    self.newline = False
+    self.indent = False
+    self.passthrough = True
+
+class StreamWrapper:
+
+  def __init__(self, interceptor, stream, prefix="  "):
+    self.interceptor = interceptor
+    self.stream = stream
+    self.prefix = prefix
+
+  def fileno(self):
+    return self.stream.fileno()
+
+  def isatty(self):
+    return self.stream.isatty()
+
+  def write(self, s):
+    if self.interceptor.passthrough:
+      self.stream.write(s)
+      return
+
+    if s:
+      self.interceptor.dirty = True
+
+    if self.interceptor.newline:
+      self.interceptor.newline = False
+      self.stream.write(" %s\n" % colorize_word("start"))
+      self.interceptor.indent = True
+    if self.interceptor.indent:
+      self.stream.write(self.prefix)
+    if s.endswith("\n"):
+      s = s.replace("\n", "\n%s" % self.prefix)[:-2]
+      self.interceptor.indent = True
+    else:
+      s = s.replace("\n", "\n%s" % self.prefix)
+      self.interceptor.indent = False
+    self.stream.write(s)
+
+    if s:
+      self.interceptor.last = s[-1]
+
+  def flush(self):
+    self.stream.flush()
+
+interceptor = Interceptor()
+
+out_wrp = StreamWrapper(interceptor, sys.stdout)
+err_wrp = StreamWrapper(interceptor, sys.stderr)
+
+out = sys.stdout
+err = sys.stderr
+sys.stdout = out_wrp
+sys.stderr = err_wrp
+
+class PatternFilter(Filter):
+
+  def __init__(self, *patterns):
+    Filter.__init__(self, patterns)
+    self.patterns = patterns
+
+  def filter(self, record):
+    if not self.patterns:
+      return True
+    for p in self.patterns:
+      if match(record.name, p):
+        return True
+    return False
+
+root = getLogger()
+handler = StreamHandler(sys.stdout)
+filter = PatternFilter(*config.log_categories)
+handler.addFilter(filter)
+handler.setFormatter(Formatter("%(asctime)s %(levelname)s %(message)s"))
+root.addHandler(handler)
+root.setLevel(WARN)
+
+log = getLogger("proton.test")
+
+PASS = "pass"
+SKIP = "skip"
+FAIL = "fail"
+
+class Runner:
+
+  def __init__(self):
+    self.exception = None
+    self.exception_phase_name = None
+    self.skip = False
+
+  def passed(self):
+    return not self.exception
+
+  def skipped(self):
+    return self.skip
+
+  def failed(self):
+    return self.exception and not self.skip
+
+  def halt(self):
+    """determines if the overall test execution should be allowed to continue to the next phase"""
+    return self.exception or self.skip
+
+  def run(self, phase_name, phase):
+    """invokes a test-phase method (which can be the test method itself or a setUp/tearDown
+       method).  If the method raises an exception the exception is examined to see if the
+       exception should be classified as a 'skipped' test"""
+    # we don't try to catch exceptions for jython because currently a
+    # jython bug will prevent the java portion of the stack being
+    # stored with the exception info in the sys module
+    if opts.bare:
+      phase()
+    else:
+      try:
+        phase()
+      except KeyboardInterrupt:
+        raise
+      except:
+        self.exception_phase_name = phase_name
+        self.exception = sys.exc_info()
+        exception_type = self.exception[0]
+        self.skip = getattr(exception_type, "skipped", False) or issubclass(exception_type, SkipTest)
+
+  def status(self):
+    if self.passed():
+      return PASS
+    elif self.skipped():
+      return SKIP
+    elif self.failed():
+      return FAIL
+    else:
+      return None
+
+  def get_formatted_exception_trace(self):
+    if self.exception:
+      if self.skip:
+        # format skipped tests without a traceback
+        output = indent("".join(traceback.format_exception_only(*self.exception[:2]))).rstrip()
+      else:
+        output = "Error during %s:" % self.exception_phase_name
+        lines = traceback.format_exception(*self.exception)
+        val = self.exception[1]
+        reflect = False
+        if val and hasattr(val, "getStackTrace"):
+          jlines = []
+          for frame in val.getStackTrace():
+            if reflect and frame.getClassName().startswith("org.python."):
+              # this is a heuristic to eliminate the jython portion of
+              # the java stack trace
+              if not opts.javatrace:
+                break
+            jlines.append("  %s\n" % frame.toString())
+            if frame.getClassName().startswith("java.lang.reflect"):
+              reflect = True
+            else:
+              reflect = False
+          lines.extend(jlines)
+        output += indent("".join(lines)).rstrip()
+      return output
+
+  def get_exception_type(self):
+    if self.exception:
+      return self.exception[0]
+    else:
+      return None
+
+  def get_exception_message(self):
+    if self.exception:
+      return self.exception[1]
+    else:
+      return None
+
+ST_WIDTH = 8
+
+def run_test(name, test, config):
+  patterns = filter.patterns
+  level = root.level
+  filter.patterns = config.log_categories
+  root.setLevel(config.log_level)
+
+  parts = name.split(".")
+  line = None
+  output = ""
+  for part in parts:
+    if line:
+      if len(line) + len(part) >= (WIDTH - ST_WIDTH - 1):
+        output += "%s. \\\n" % line
+        line = "    %s" % part
+      else:
+        line = "%s.%s" % (line, part)
+    else:
+      line = part
+
+  if line:
+    output += "%s %s" % (line, (((WIDTH - ST_WIDTH) - len(line))*"."))
+  sys.stdout.write(output)
+  sys.stdout.flush()
+  interceptor.begin()
+  start = time.time()
+  try:
+    runner = test()
+  finally:
+    interceptor.reset()
+  end = time.time()
+  if interceptor.dirty:
+    if interceptor.last != "\n":
+      sys.stdout.write("\n")
+    sys.stdout.write(output)
+  print(" %s" % colorize_word(runner.status()))
+  if runner.failed() or runner.skipped():
+    print(runner.get_formatted_exception_trace())
+  root.setLevel(level)
+  filter.patterns = patterns
+  return TestResult(end - start,
+                    runner.passed(),
+                    runner.skipped(),
+                    runner.failed(),
+                    runner.get_exception_type(),
+                    runner.get_exception_message(),
+                    runner.get_formatted_exception_trace())
+
+class TestResult:
+
+  def __init__(self, time, passed, skipped, failed, exception_type, exception_message, formatted_exception_trace):
+    self.time = time
+    self.passed = passed
+    self.skipped = skipped
+    self.failed = failed
+    self.exception_type =  exception_type
+    self.exception_message = exception_message
+    self.formatted_exception_trace = formatted_exception_trace
+
+class FunctionTest:
+
+  def __init__(self, test):
+    self.test = test
+
+  def name(self):
+    return "%s.%s" % (self.test.__module__, self.test.__name__)
+
+  def run(self):
+    return run_test(self.name(), self._run, config)
+
+  def _run(self):
+    runner = Runner()
+    runner.run("test", lambda: self.test(config))
+    return runner
+
+  def __repr__(self):
+    return "FunctionTest(%r)" % self.test
+
+class MethodTest:
+
+  def __init__(self, cls, method):
+    self.cls = cls
+    self.method = method
+
+  def name(self):
+    return "%s.%s.%s" % (self.cls.__module__, self.cls.__name__, self.method)
+
+  def run(self):
+    return run_test(self.name(), self._run, config)
+
+  def _run(self):
+    runner = Runner()
+    inst = self.cls(self.method)
+    test = getattr(inst, self.method)
+
+    if hasattr(inst, "configure"):
+      runner.run("configure", lambda: inst.configure(config))
+      if runner.halt(): return runner
+    if hasattr(inst, "setUp"):
+      runner.run("setup", inst.setUp)
+      if runner.halt(): return runner
+
+    runner.run("test", test)
+
+    if hasattr(inst, "tearDown"):
+      runner.run("teardown", inst.tearDown)
+
+    return runner
+
+  def __repr__(self):
+    return "MethodTest(%r, %r)" % (self.cls, self.method)
+
+class PatternMatcher:
+
+  def __init__(self, *patterns):
+    self.patterns = patterns
+
+  def matches(self, name):
+    for p in self.patterns:
+      if match(name, p):
+        return True
+    return False
+
+class FunctionScanner(PatternMatcher):
+
+  def inspect(self, obj):
+    return type(obj) == types.FunctionType and self.matches(obj.__name__)
+
+  def descend(self, func):
+    # the None is required for older versions of python
+    return; yield None
+
+  def extract(self, func):
+    yield FunctionTest(func)
+
+class ClassScanner(PatternMatcher):
+
+  def inspect(self, obj):
+    return type(obj) in CLASS_TYPES and self.matches(obj.__name__)
+
+  def descend(self, cls):
+    # the None is required for older versions of python
+    return; yield None
+
+  def extract(self, cls):
+    names = dir(cls)
+    names.sort()
+    for name in names:
+      obj = getattr(cls, name)
+      if hasattr(obj, '__call__') and name.startswith("test"):
+        yield MethodTest(cls, name)
+
+class ModuleScanner:
+
+  def inspect(self, obj):
+    return type(obj) == types.ModuleType
+
+  def descend(self, obj):
+    names = dir(obj)
+    names.sort()
+    for name in names:
+      yield getattr(obj, name)
+
+  def extract(self, obj):
+    # the None is required for older versions of python
+    return; yield None
+
+class Harness:
+
+  def __init__(self):
+    self.scanners = [
+      ModuleScanner(),
+      ClassScanner("*Test", "*Tests", "*TestCase"),
+      FunctionScanner("test_*")
+      ]
+    self.tests = []
+    self.scanned = []
+
+  def scan(self, *roots):
+    objects = list(roots)
+
+    while objects:
+      obj = objects.pop(0)
+      for s in self.scanners:
+        if s.inspect(obj):
+          self.tests.extend(s.extract(obj))
+          for child in s.descend(obj):
+            if not (child in self.scanned or child in objects):
+              objects.append(child)
+      self.scanned.append(obj)
+
+modules = opts.modules
+if not modules:
+  modules.extend(["proton_tests"])
+h = Harness()
+for name in modules:
+  m = __import__(name, None, None, ["dummy"])
+  h.scan(m)
+
+filtered = [t for t in h.tests if is_included(t.name())]
+ignored = [t for t in h.tests if is_ignored(t.name())]
+total = len(filtered) + len(ignored)
+
+if opts.xml and not list_only:
+   xmlr = JunitXmlStyleReporter(opts.xml);
+   xmlr.begin();
+else:
+   xmlr = None
+
+def runthrough():
+  passed = 0
+  failed = 0
+  skipped = 0
+  start = time.time()
+  for t in filtered:
+    if list_only:
+      print(t.name())
+    else:
+      st = t.run()
+      if xmlr:
+        xmlr.report(t.name(), st)
+      if st.passed:
+        passed += 1
+      elif st.skipped:
+        skipped += 1
+      elif st.failed:
+        failed += 1
+        if opts.hoe:
+          break
+  end = time.time()
+
+  run = passed + failed
+
+  if not list_only:
+    if passed:
+      _pass = "pass"
+    else:
+      _pass = "fail"
+    if failed:
+      outcome = "fail"
+    else:
+      outcome = "pass"
+    if ignored:
+      ign = "ignored"
+    else:
+      ign = "pass"
+    if skipped:
+      skip = "skip"
+    else:
+      skip = "pass"
+    sys.stdout.write(colorize("Totals: ", 1))
+    totals = [colorize_word("total", "%s tests" % total),
+              colorize_word(_pass, "%s passed" % passed),
+              colorize_word(skip, "%s skipped" % skipped),
+              colorize_word(ign, "%s ignored" % len(ignored)),
+              colorize_word(outcome, "%s failed" % failed)]
+    sys.stdout.write(", ".join(totals))
+    if opts.hoe and failed > 0:
+      print(" -- (halted after %s)" % run)
+    else:
+      print("")
+    if opts.time and run > 0:
+      sys.stdout.write(colorize("Timing:", 1))
+      timing = [colorize_word("elapsed", "%.2fs elapsed" % (end - start)),
+                colorize_word("average", "%.2fs average" % ((end - start)/run))]
+      print(", ".join(timing))
+
+  if xmlr:
+     xmlr.end()
+
+  return failed
+
+limit = opts.count
+count = 0
+failures = False
+while limit == 0 or count < limit:
+  count += 1
+  if runthrough():
+    failures = True
+    if count > 1:
+      print(" -- (failures after %s runthroughs)" % count)
+  else:
+    continue
+
+if failures:
+  sys.exit(1)
+else:
+  sys.exit(0)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/__init__.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/__init__.py b/python/tests/proton_tests/__init__.py
new file mode 100644
index 0000000..cc75c6c
--- /dev/null
+++ b/python/tests/proton_tests/__init__.py
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+import proton_tests.codec
+import proton_tests.engine
+import proton_tests.message
+import proton_tests.handler
+import proton_tests.reactor
+import proton_tests.sasl
+import proton_tests.transport
+import proton_tests.ssl
+import proton_tests.interop
+import proton_tests.soak
+import proton_tests.url
+import proton_tests.utils

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/codec.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/codec.py b/python/tests/proton_tests/codec.py
new file mode 100644
index 0000000..43fe09a
--- /dev/null
+++ b/python/tests/proton_tests/codec.py
@@ -0,0 +1,401 @@
+#
+# 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.
+#
+
+import os, sys
+from . import common
+from proton import *
+from proton._compat import raise_
+from uuid import uuid4
+
+class Test(common.Test):
+
+  def setUp(self):
+    self.data = Data()
+
+  def tearDown(self):
+    self.data = None
+
+class DataTest(Test):
+
+  def testTopLevelNext(self):
+    assert self.data.next() is None
+    self.data.put_null()
+    self.data.put_bool(False)
+    self.data.put_int(0)
+    assert self.data.next() is None
+    self.data.rewind()
+    assert self.data.next() == Data.NULL
+    assert self.data.next() == Data.BOOL
+    assert self.data.next() == Data.INT
+    assert self.data.next() is None
+
+  def testNestedNext(self):
+    assert self.data.next() is None
+    self.data.put_null()
+    assert self.data.next() is None
+    self.data.put_list()
+    assert self.data.next() is None
+    self.data.put_bool(False)
+    assert self.data.next() is None
+    self.data.rewind()
+    assert self.data.next() is Data.NULL
+    assert self.data.next() is Data.LIST
+    self.data.enter()
+    assert self.data.next() is None
+    self.data.put_ubyte(0)
+    assert self.data.next() is None
+    self.data.put_uint(0)
+    assert self.data.next() is None
+    self.data.put_int(0)
+    assert self.data.next() is None
+    self.data.exit()
+    assert self.data.next() is Data.BOOL
+    assert self.data.next() is None
+
+    self.data.rewind()
+    assert self.data.next() is Data.NULL
+    assert self.data.next() is Data.LIST
+    assert self.data.enter()
+    assert self.data.next() is Data.UBYTE
+    assert self.data.next() is Data.UINT
+    assert self.data.next() is Data.INT
+    assert self.data.next() is None
+    assert self.data.exit()
+    assert self.data.next() is Data.BOOL
+    assert self.data.next() is None
+
+  def testEnterExit(self):
+    assert self.data.next() is None
+    assert not self.data.enter()
+    self.data.put_list()
+    assert self.data.enter()
+    assert self.data.next() is None
+    self.data.put_list()
+    assert self.data.enter()
+    self.data.put_list()
+    assert self.data.enter()
+    assert self.data.exit()
+    assert self.data.get_list() == 0
+    assert self.data.exit()
+    assert self.data.get_list() == 1
+    assert self.data.exit()
+    assert self.data.get_list() == 1
+    assert not self.data.exit()
+    assert self.data.get_list() == 1
+    assert self.data.next() is None
+
+    self.data.rewind()
+    assert self.data.next() is Data.LIST
+    assert self.data.get_list() == 1
+    assert self.data.enter()
+    assert self.data.next() is Data.LIST
+    assert self.data.get_list() == 1
+    assert self.data.enter()
+    assert self.data.next() is Data.LIST
+    assert self.data.get_list() == 0
+    assert self.data.enter()
+    assert self.data.next() is None
+    assert self.data.exit()
+    assert self.data.get_list() == 0
+    assert self.data.exit()
+    assert self.data.get_list() == 1
+    assert self.data.exit()
+    assert self.data.get_list() == 1
+    assert not self.data.exit()
+
+
+  def put(self, putter, v):
+    """More informative exception from putters, include bad value"""
+    try:
+      putter(v)
+    except Exception:
+      etype, value, trace = sys.exc_info()
+      raise_(etype, etype("%s(%r): %s" % (putter.__name__, v, value)), trace)
+    return putter
+
+  # (bits, signed) for each integer type
+  INT_TYPES = {
+    "byte": (8, True),
+    "ubyte": (8, False),
+    "short": (16, True),
+    "ushort": (16, False),
+    "int": (32, True),
+    "uint": (32, False),
+    "long": (64, True),
+    "ulong": (64, False)
+  }
+
+  def int_values(self, dtype):
+    """Set of test values for integer type dtype, include extreme and medial values"""
+    bits, signed = self.INT_TYPES[dtype]
+    values = [0, 1, 2, 5, 42]
+    if signed:
+      min, max = -2**(bits-1), 2**(bits-1)-1
+      values.append(max // 2)
+      values += [-i for i in values if i]
+      values += [min, max]
+    else:
+      max = 2**(bits) - 1
+      values += [max // 2, max]
+    return sorted(values)
+
+  def _testArray(self, dtype, descriptor, atype, *values):
+    if dtype: dTYPE = getattr(self.data, dtype.upper())
+    aTYPE = getattr(self.data, atype.upper())
+    self.data.put_array(dtype is not None, aTYPE)
+    self.data.enter()
+    if dtype is not None:
+      putter = getattr(self.data, "put_%s" % dtype)
+      self.put(putter, descriptor)
+    putter = getattr(self.data, "put_%s" % atype)
+    for v in values:
+      self.put(putter, v)
+    self.data.exit()
+    self.data.rewind()
+    assert self.data.next() == Data.ARRAY
+    count, described, type = self.data.get_array()
+    assert count == len(values), count
+    if dtype is None:
+      assert described == False
+    else:
+      assert described == True
+    assert type == aTYPE, type
+    assert self.data.enter()
+    if described:
+      assert self.data.next() == dTYPE
+      getter = getattr(self.data, "get_%s" % dtype)
+      gotten = getter()
+      assert gotten == descriptor, gotten
+    if values:
+      getter = getattr(self.data, "get_%s" % atype)
+      for v in values:
+        assert self.data.next() == aTYPE
+        gotten = getter()
+        assert gotten == v, gotten
+    assert self.data.next() is None
+    assert self.data.exit()
+
+  def testStringArray(self):
+    self._testArray(None, None, "string", "one", "two", "three")
+
+  def testDescribedStringArray(self):
+    self._testArray("symbol", "url", "string", "one", "two", "three")
+
+  def _test_int_array(self, atype):
+    self._testArray(None, None, atype, *self.int_values(atype))
+
+  def testByteArray(self): self._test_int_array("byte")
+  def testUbyteArray(self): self._test_int_array("ubyte")
+  def testShortArray(self): self._test_int_array("short")
+  def testUshortArray(self): self._test_int_array("ushort")
+  def testIntArray(self): self._test_int_array("int")
+  def testUintArray(self): self._test_int_array("uint")
+  def testLongArray(self): self._test_int_array("long")
+  def testUlongArray(self): self._test_int_array("ulong")
+
+  def testUUIDArray(self):
+    self._testArray(None, None, "uuid", uuid4(), uuid4(), uuid4())
+
+  def testEmptyArray(self):
+    self._testArray(None, None, "null")
+
+  def testDescribedEmptyArray(self):
+    self._testArray("long", 0, "null")
+
+  def _test(self, dtype, *values, **kwargs):
+    eq=kwargs.get("eq", lambda x, y: x == y)
+    ntype = getattr(Data, dtype.upper())
+    putter = getattr(self.data, "put_%s" % dtype)
+    getter = getattr(self.data, "get_%s" % dtype)
+
+    for v in values:
+      self.put(putter, v)
+      gotten = getter()
+      assert eq(gotten, v), (gotten, v)
+
+    self.data.rewind()
+
+    for v in values:
+      vtype = self.data.next()
+      assert vtype == ntype, vtype
+      gotten = getter()
+      assert eq(gotten, v), (gotten, v)
+
+    encoded = self.data.encode()
+    copy = Data(0)
+    while encoded:
+      n = copy.decode(encoded)
+      encoded = encoded[n:]
+    copy.rewind()
+
+    cgetter = getattr(copy, "get_%s" % dtype)
+
+    for v in values:
+      vtype = copy.next()
+      assert vtype == ntype, vtype
+      gotten = cgetter()
+      assert eq(gotten, v), (gotten, v)
+
+  def _test_int(self, itype):
+    self._test(itype, *self.int_values(itype))
+
+  def testByte(self): self._test_int("byte")
+  def testUbyte(self): self._test_int("ubyte")
+  def testShort(self): self._test_int("short")
+  def testUshort(self): self._test("ushort")
+  def testInt(self): self._test_int("int")
+  def testUint(self): self._test_int("uint")
+  def testLong(self): self._test_int("long")
+  def testUlong(self): self._test_int("ulong")
+
+  def testString(self):
+    self._test("string", "one", "two", "three", "this is a test", "")
+
+  def testFloat(self):
+    # we have to use a special comparison here because python
+    # internally only uses doubles and converting between floats and
+    # doubles is imprecise
+    self._test("float", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3,
+               eq=lambda x, y: x - y < 0.000001)
+
+  def testDouble(self):
+    self._test("double", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3)
+
+  def testBinary(self):
+    self._test("binary", b"this", b"is", b"a", b"test",b"of" b"b\x00inary")
+
+  def testSymbol(self):
+    self._test("symbol", symbol("this is a symbol test"), symbol("bleh"), symbol("blah"))
+
+  def testTimestamp(self):
+    self._test("timestamp", timestamp(0), timestamp(12345), timestamp(1000000))
+
+  def testChar(self):
+    self._test("char", char('a'), char('b'), char('c'), char(u'\u20AC'))
+
+  def testUUID(self):
+    self._test("uuid", uuid4(), uuid4(), uuid4())
+
+  def testDecimal32(self):
+    self._test("decimal32", decimal32(0), decimal32(1), decimal32(2), decimal32(3), decimal32(4), decimal32(2**30))
+
+  def testDecimal64(self):
+    self._test("decimal64", decimal64(0), decimal64(1), decimal64(2), decimal64(3), decimal64(4), decimal64(2**60))
+
+  def testDecimal128(self):
+    self._test("decimal128", decimal128(b"fdsaasdf;lkjjkl;"), decimal128(b"x"*16))
+
+  def testCopy(self):
+    self.data.put_described()
+    self.data.enter()
+    self.data.put_ulong(123)
+    self.data.put_map()
+    self.data.enter()
+    self.data.put_string("pi")
+    self.data.put_double(3.14159265359)
+
+    dst = Data()
+    dst.copy(self.data)
+
+    copy = dst.format()
+    orig = self.data.format()
+    assert copy == orig, (copy, orig)
+
+  def testCopyNested(self):
+    nested = [1, 2, 3, [4, 5, 6], 7, 8, 9]
+    self.data.put_object(nested)
+    dst = Data()
+    dst.copy(self.data)
+    assert dst.format() == self.data.format()
+
+  def testCopyNestedArray(self):
+    nested = [Array(UNDESCRIBED, Data.LIST,
+                    ["first", [Array(UNDESCRIBED, Data.INT, 1,2,3)]],
+                    ["second", [Array(UNDESCRIBED, Data.INT, 1,2,3)]],
+                    ["third", [Array(UNDESCRIBED, Data.INT, 1,2,3)]],
+                    ),
+              "end"]
+    self.data.put_object(nested)
+    dst = Data()
+    dst.copy(self.data)
+    assert dst.format() == self.data.format()
+
+  def testRoundTrip(self):
+    obj = {symbol("key"): timestamp(1234),
+           ulong(123): "blah",
+           char("c"): "bleh",
+           u"desc": Described(symbol("url"), u"http://example.org"),
+           u"array": Array(UNDESCRIBED, Data.INT, 1, 2, 3),
+           u"list": [1, 2, 3, None, 4],
+           u"boolean": True}
+    self.data.put_object(obj)
+    enc = self.data.encode()
+    data = Data()
+    data.decode(enc)
+    data.rewind()
+    assert data.next()
+    copy = data.get_object()
+    assert copy == obj, (copy, obj)
+
+  def testBuffer(self):
+    try:
+      self.data.put_object(buffer(b"foo"))
+    except NameError:
+      # python >= 3.0 does not have `buffer`
+      return
+    data = Data()
+    data.decode(self.data.encode())
+    data.rewind()
+    assert data.next()
+    assert data.type() == Data.BINARY
+    assert data.get_object() == b"foo"
+
+  def testMemoryView(self):
+    try:
+      self.data.put_object(memoryview(b"foo"))
+    except NameError:
+      # python <= 2.6 does not have `memoryview`
+      return
+    data = Data()
+    data.decode(self.data.encode())
+    data.rewind()
+    assert data.next()
+    assert data.type() == Data.BINARY
+    assert data.get_object() == b"foo"
+
+  def testLookup(self):
+    obj = {symbol("key"): u"value",
+           symbol("pi"): 3.14159,
+           symbol("list"): [1, 2, 3, 4]}
+    self.data.put_object(obj)
+    self.data.rewind()
+    self.data.next()
+    self.data.enter()
+    self.data.narrow()
+    assert self.data.lookup("pi")
+    assert self.data.get_object() == 3.14159
+    self.data.rewind()
+    assert self.data.lookup("key")
+    assert self.data.get_object() == u"value"
+    self.data.rewind()
+    assert self.data.lookup("list")
+    assert self.data.get_object() == [1, 2, 3, 4]
+    self.data.widen()
+    self.data.rewind()
+    assert not self.data.lookup("pi")

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/common.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/common.py b/python/tests/proton_tests/common.py
new file mode 100644
index 0000000..90ba34c
--- /dev/null
+++ b/python/tests/proton_tests/common.py
@@ -0,0 +1,510 @@
+#
+# 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.
+#
+
+from unittest import TestCase
+try:
+  from unittest import SkipTest
+except:
+  try:
+    from unittest2 import SkipTest
+  except:
+    class SkipTest(Exception):
+      pass
+
+from random import randint
+from threading import Thread
+from socket import socket, AF_INET, SOCK_STREAM
+from subprocess import Popen,PIPE,STDOUT
+import sys, os, subprocess
+from proton import SASL, SSL
+from proton.reactor import Container
+from proton.handlers import Handshaker, FlowController
+from string import Template
+
+def free_tcp_ports(count=1):
+  """ return a list of 'count' TCP ports that are free to used (ie. unbound)
+  """
+  retry = 0
+  ports = []
+  sockets = []
+  while len(ports) != count:
+    port = randint(49152, 65535)
+    sockets.append( socket( AF_INET, SOCK_STREAM ) )
+    try:
+      sockets[-1].bind( ("0.0.0.0", port ) )
+      ports.append( port )
+      retry = 0
+    except:
+      retry += 1
+      assert retry != 100, "No free sockets available for test!"
+  for s in sockets:
+    s.close()
+  return ports
+
+def free_tcp_port():
+  return free_tcp_ports(1)[0]
+
+def pump_uni(src, dst, buffer_size=1024):
+  p = src.pending()
+  c = dst.capacity()
+
+  if c < 0:
+    if p < 0:
+      return False
+    else:
+      src.close_head()
+      return True
+
+  if p < 0:
+    dst.close_tail()
+  elif p == 0 or c == 0:
+    return False
+  else:
+    binary = src.peek(min(c, buffer_size))
+    dst.push(binary)
+    src.pop(len(binary))
+
+  return True
+
+def pump(transport1, transport2, buffer_size=1024):
+  """ Transfer all pending bytes between two Proton engines
+      by repeatedly calling peek/pop and push.
+      Asserts that each engine accepts some bytes every time
+      (unless it's already closed).
+  """
+  while (pump_uni(transport1, transport2, buffer_size) or
+         pump_uni(transport2, transport1, buffer_size)):
+    pass
+
+def findfileinpath(filename, searchpath):
+    """Find filename in the searchpath
+        return absolute path to the file or None
+    """
+    paths = searchpath.split(os.pathsep)
+    for path in paths:
+        if os.path.exists(os.path.join(path, filename)):
+            return os.path.abspath(os.path.join(path, filename))
+    return None
+
+def isSSLPresent():
+    return SSL.present()
+
+createdSASLDb = False
+
+def _cyrusSetup(conf_dir):
+  """Write out simple SASL config.
+  """
+  saslpasswd = ""
+  if 'SASLPASSWD' in os.environ:
+    saslpasswd = os.environ['SASLPASSWD']
+  else:
+    saslpasswd = findfileinpath('saslpasswd2', os.getenv('PATH')) or ""
+  if os.path.exists(saslpasswd):
+    t = Template("""sasldb_path: ${db}
+mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS
+""")
+    abs_conf_dir = os.path.abspath(conf_dir)
+    subprocess.call(args=['rm','-rf',abs_conf_dir])
+    os.mkdir(abs_conf_dir)
+    db = os.path.join(abs_conf_dir,'proton.sasldb')
+    conf = os.path.join(abs_conf_dir,'proton-server.conf')
+    f = open(conf, 'w')
+    f.write(t.substitute(db=db))
+    f.close()
+
+    cmd_template = Template("echo password | ${saslpasswd} -c -p -f ${db} -u proton user")
+    cmd = cmd_template.substitute(db=db, saslpasswd=saslpasswd)
+    subprocess.call(args=cmd, shell=True)
+
+    os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir
+    global createdSASLDb
+    createdSASLDb = True
+
+# Globally initialize Cyrus SASL configuration
+if SASL.extended():
+  _cyrusSetup('sasl-conf')
+
+def ensureCanTestExtendedSASL():
+  if not SASL.extended():
+    raise Skipped('Extended SASL not supported')
+  if not createdSASLDb:
+    raise Skipped("Can't Test Extended SASL: Couldn't create auth db")
+
+class DefaultConfig:
+    defines = {}
+
+class Test(TestCase):
+  config = DefaultConfig()
+
+  def __init__(self, name):
+    super(Test, self).__init__(name)
+    self.name = name
+
+  def configure(self, config):
+    self.config = config
+
+  def default(self, name, value, **profiles):
+    default = value
+    profile = self.config.defines.get("profile")
+    if profile:
+      default = profiles.get(profile, default)
+    return self.config.defines.get(name, default)
+
+  @property
+  def delay(self):
+    return float(self.default("delay", "1", fast="0.1"))
+
+  @property
+  def timeout(self):
+    return float(self.default("timeout", "60", fast="10"))
+
+  @property
+  def verbose(self):
+    return int(self.default("verbose", 0))
+
+
+class Skipped(SkipTest):
+  skipped = True
+
+
+class TestServer(object):
+  """ Base class for creating test-specific message servers.
+  """
+  def __init__(self, **kwargs):
+    self.args = kwargs
+    self.reactor = Container(self)
+    self.host = "127.0.0.1"
+    self.port = 0
+    if "host" in kwargs:
+      self.host = kwargs["host"]
+    if "port" in kwargs:
+      self.port = kwargs["port"]
+    self.handlers = [FlowController(10), Handshaker()]
+    self.thread = Thread(name="server-thread", target=self.run)
+    self.thread.daemon = True
+    self.running = True
+    self.conditions = []
+
+  def start(self):
+    self.reactor.start()
+    retry = 0
+    if self.port == 0:
+      self.port = str(randint(49152, 65535))
+      retry = 10
+    while retry > 0:
+      try:
+        self.acceptor = self.reactor.acceptor(self.host, self.port)
+        break
+      except IOError:
+        self.port = str(randint(49152, 65535))
+        retry -= 1
+    assert retry > 0, "No free port for server to listen on!"
+    self.thread.start()
+
+  def stop(self):
+    self.running = False
+    self.reactor.wakeup()
+    self.thread.join()
+
+  # Note: all following methods all run under the thread:
+
+  def run(self):
+    self.reactor.timeout = 3.14159265359
+    while self.reactor.process():
+      if not self.running:
+        self.acceptor.close()
+        self.reactor.stop()
+        break
+
+  def on_connection_bound(self, event):
+    if "idle_timeout" in self.args:
+      event.transport.idle_timeout = self.args["idle_timeout"]
+
+  def on_connection_local_close(self, event):
+    self.conditions.append(event.connection.condition)
+
+  def on_delivery(self, event):
+    event.delivery.settle()
+
+#
+# Classes that wrap the messenger applications msgr-send and msgr-recv.
+# These applications reside in the c/tools directory
+#
+
+class MessengerApp(object):
+    """ Interface to control a MessengerApp """
+    def __init__(self):
+        self._cmdline = None
+        # options common to Receivers and Senders:
+        self.ca_db = None
+        self.certificate = None
+        self.privatekey = None
+        self.password = None
+        self._output = None
+
+    def start(self, verbose=False):
+        """ Begin executing the test """
+        cmd = self.cmdline()
+        self._verbose = verbose
+        if self._verbose:
+            print("COMMAND='%s'" % str(cmd))
+        #print("ENV='%s'" % str(os.environ.copy()))
+        try:
+            # Handle python launch by replacing script 'filename' with
+            # 'python abspath-to-filename' in cmdline arg list.
+            if cmd[0].endswith('.py'):
+                foundfile = findfileinpath(cmd[0], os.getenv('PATH'))
+                if foundfile is None:
+                    msg = "Unable to locate file '%s' in PATH" % cmd[0]
+                    raise Skipped("Skipping test - %s" % msg)
+
+                del cmd[0:1]
+                cmd.insert(0, foundfile)
+                cmd.insert(0, sys.executable)
+            self._process = Popen(cmd, stdout=PIPE, stderr=STDOUT,
+                                  bufsize=4096, universal_newlines=True)
+        except OSError:
+            e = sys.exc_info()[1]
+            print("ERROR: '%s'" % e)
+            msg = "Unable to execute command '%s', is it in your PATH?" % cmd[0]
+
+            # NOTE(flaper87): Skip the test if the command is not found.
+            if e.errno == 2:
+              raise Skipped("Skipping test - %s" % msg)
+            assert False, msg
+
+        self._ready()  # wait for it to initialize
+
+    def stop(self):
+        """ Signal the client to start clean shutdown """
+        pass
+
+    def wait(self):
+        """ Wait for client to complete """
+        self._output = self._process.communicate()
+        if self._verbose:
+            print("OUTPUT='%s'" % self.stdout())
+
+    def status(self):
+        """ Return status from client process """
+        return self._process.returncode
+
+    def stdout(self):
+        #self._process.communicate()[0]
+        if not self._output or not self._output[0]:
+            return "*** NO STDOUT ***"
+        return self._output[0]
+
+    def stderr(self):
+        if not self._output or not self._output[1]:
+            return "*** NO STDERR ***"
+        return self._output[1]
+
+    def cmdline(self):
+        if not self._cmdline:
+            self._build_command()
+        return self._cmdline
+
+    def _build_command(self):
+        assert False, "_build_command() needs override"
+
+    def _ready(self):
+        assert False, "_ready() needs override"
+
+    def _do_common_options(self):
+        """ Common option handling """
+        if self.ca_db is not None:
+            self._cmdline.append("-T")
+            self._cmdline.append(str(self.ca_db))
+        if self.certificate is not None:
+            self._cmdline.append("-C")
+            self._cmdline.append(str(self.certificate))
+        if self.privatekey is not None:
+            self._cmdline.append("-K")
+            self._cmdline.append(str(self.privatekey))
+        if self.password is not None:
+            self._cmdline.append("-P")
+            self._cmdline.append("pass:" + str(self.password))
+
+
+class MessengerSender(MessengerApp):
+    """ Interface to configure a sending MessengerApp """
+    def __init__(self):
+        MessengerApp.__init__(self)
+        self._command = None
+        # @todo make these properties
+        self.targets = []
+        self.send_count = None
+        self.msg_size = None
+        self.send_batch = None
+        self.outgoing_window = None
+        self.report_interval = None
+        self.get_reply = False
+        self.timeout = None
+        self.incoming_window = None
+        self.recv_count = None
+        self.name = None
+
+    # command string?
+    def _build_command(self):
+        self._cmdline = self._command
+        self._do_common_options()
+        assert self.targets, "Missing targets, required for sender!"
+        self._cmdline.append("-a")
+        self._cmdline.append(",".join(self.targets))
+        if self.send_count is not None:
+            self._cmdline.append("-c")
+            self._cmdline.append(str(self.send_count))
+        if self.msg_size is not None:
+            self._cmdline.append("-b")
+            self._cmdline.append(str(self.msg_size))
+        if self.send_batch is not None:
+            self._cmdline.append("-p")
+            self._cmdline.append(str(self.send_batch))
+        if self.outgoing_window is not None:
+            self._cmdline.append("-w")
+            self._cmdline.append(str(self.outgoing_window))
+        if self.report_interval is not None:
+            self._cmdline.append("-e")
+            self._cmdline.append(str(self.report_interval))
+        if self.get_reply:
+            self._cmdline.append("-R")
+        if self.timeout is not None:
+            self._cmdline.append("-t")
+            self._cmdline.append(str(self.timeout))
+        if self.incoming_window is not None:
+            self._cmdline.append("-W")
+            self._cmdline.append(str(self.incoming_window))
+        if self.recv_count is not None:
+            self._cmdline.append("-B")
+            self._cmdline.append(str(self.recv_count))
+        if self.name is not None:
+            self._cmdline.append("-N")
+            self._cmdline.append(str(self.name))
+
+    def _ready(self):
+        pass
+
+
+class MessengerReceiver(MessengerApp):
+    """ Interface to configure a receiving MessengerApp """
+    def __init__(self):
+        MessengerApp.__init__(self)
+        self._command = None
+        # @todo make these properties
+        self.subscriptions = []
+        self.receive_count = None
+        self.recv_count = None
+        self.incoming_window = None
+        self.timeout = None
+        self.report_interval = None
+        self.send_reply = False
+        self.outgoing_window = None
+        self.forwards = []
+        self.name = None
+
+    # command string?
+    def _build_command(self):
+        self._cmdline = self._command
+        self._do_common_options()
+        self._cmdline += ["-X", "READY"]
+        assert self.subscriptions, "Missing subscriptions, required for receiver!"
+        self._cmdline.append("-a")
+        self._cmdline.append(",".join(self.subscriptions))
+        if self.receive_count is not None:
+            self._cmdline.append("-c")
+            self._cmdline.append(str(self.receive_count))
+        if self.recv_count is not None:
+            self._cmdline.append("-b")
+            self._cmdline.append(str(self.recv_count))
+        if self.incoming_window is not None:
+            self._cmdline.append("-w")
+            self._cmdline.append(str(self.incoming_window))
+        if self.timeout is not None:
+            self._cmdline.append("-t")
+            self._cmdline.append(str(self.timeout))
+        if self.report_interval is not None:
+            self._cmdline.append("-e")
+            self._cmdline.append(str(self.report_interval))
+        if self.send_reply:
+            self._cmdline.append("-R")
+        if self.outgoing_window is not None:
+            self._cmdline.append("-W")
+            self._cmdline.append(str(self.outgoing_window))
+        if self.forwards:
+            self._cmdline.append("-F")
+            self._cmdline.append(",".join(self.forwards))
+        if self.name is not None:
+            self._cmdline.append("-N")
+            self._cmdline.append(str(self.name))
+
+    def _ready(self):
+        """ wait for subscriptions to complete setup. """
+        r = self._process.stdout.readline()
+        assert r.strip() == "READY", "Unexpected input while waiting for receiver to initialize: %s" % r
+
+class MessengerSenderC(MessengerSender):
+    def __init__(self):
+        MessengerSender.__init__(self)
+        self._command = ["msgr-send"]
+
+def setup_valgrind(self):
+    if "VALGRIND" not in os.environ:
+        raise Skipped("Skipping test - $VALGRIND not set.")
+    super(type(self), self).__init__()
+    self._command = [os.environ["VALGRIND"]] + os.environ["VALGRIND_ARGS"].split(' ') + self._command
+
+class MessengerSenderValgrind(MessengerSenderC):
+    """ Run the C sender under Valgrind
+    """
+    def __init__(self, suppressions=None):
+        setup_valgrind(self)
+
+class MessengerReceiverC(MessengerReceiver):
+    def __init__(self):
+        MessengerReceiver.__init__(self)
+        self._command = ["msgr-recv"]
+
+class MessengerReceiverValgrind(MessengerReceiverC):
+    """ Run the C receiver under Valgrind
+    """
+    def __init__(self, suppressions=None):
+        setup_valgrind(self)
+
+class ReactorSenderC(MessengerSender):
+    def __init__(self):
+        MessengerSender.__init__(self)
+        self._command = ["reactor-send"]
+
+class ReactorSenderValgrind(ReactorSenderC):
+    """ Run the C sender under Valgrind
+    """
+    def __init__(self, suppressions=None):
+        setup_valgrind(self)
+
+class ReactorReceiverC(MessengerReceiver):
+    def __init__(self):
+        MessengerReceiver.__init__(self)
+        self._command = ["reactor-recv"]
+
+class ReactorReceiverValgrind(ReactorReceiverC):
+    """ Run the C receiver under Valgrind
+    """
+    def __init__(self, suppressions=None):
+        setup_valgrind(self)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[07/11] qpid-proton git commit: PROTON-1885: [python] move tests/python to python/tests

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/transport.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/transport.py b/python/tests/proton_tests/transport.py
new file mode 100644
index 0000000..236169d
--- /dev/null
+++ b/python/tests/proton_tests/transport.py
@@ -0,0 +1,393 @@
+#
+# 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.
+#
+
+import os
+import sys
+from . import common
+from proton import *
+
+
+class Test(common.Test):
+  pass
+
+class ClientTransportTest(Test):
+
+  def setUp(self):
+    self.transport = Transport()
+    self.peer = Transport()
+    self.conn = Connection()
+    self.peer.bind(self.conn)
+
+  def tearDown(self):
+    self.transport = None
+    self.peer = None
+    self.conn = None
+
+  def drain(self):
+    while True:
+      p = self.transport.pending()
+      if p < 0:
+        return
+      elif p > 0:
+        data = self.transport.peek(p)
+        self.peer.push(data)
+        self.transport.pop(len(data))
+      else:
+        assert False
+
+  def assert_error(self, name):
+    assert self.conn.remote_container is None, self.conn.remote_container
+    self.drain()
+    # verify that we received an open frame
+    assert self.conn.remote_container is not None, self.conn.remote_container
+    # verify that we received a close frame
+    assert self.conn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_CLOSED, self.conn.state
+    # verify that a framing error was reported
+    assert self.conn.remote_condition.name == name, self.conn.remote_condition
+
+  def testEOS(self):
+    self.transport.push(b"") # should be a noop
+    self.transport.close_tail() # should result in framing error
+    self.assert_error(u'amqp:connection:framing-error')
+
+  def testPartial(self):
+    self.transport.push(b"AMQ") # partial header
+    self.transport.close_tail() # should result in framing error
+    self.assert_error(u'amqp:connection:framing-error')
+
+  def testGarbage(self, garbage=b"GARBAGE_"):
+    self.transport.push(garbage)
+    self.assert_error(u'amqp:connection:framing-error')
+    assert self.transport.pending() < 0
+    self.transport.close_tail()
+    assert self.transport.pending() < 0
+
+  def testSmallGarbage(self):
+    self.testGarbage(b"XXX")
+
+  def testBigGarbage(self):
+    self.testGarbage(b"GARBAGE_XXX")
+
+  def testHeader(self):
+    self.transport.push(b"AMQP\x00\x01\x00\x00")
+    self.transport.close_tail()
+    self.assert_error(u'amqp:connection:framing-error')
+
+  def testHeaderBadDOFF1(self):
+    """Verify doff > size error"""
+    self.testGarbage(b"AMQP\x00\x01\x00\x00\x00\x00\x00\x08\x08\x00\x00\x00")
+
+  def testHeaderBadDOFF2(self):
+    """Verify doff < 2 error"""
+    self.testGarbage(b"AMQP\x00\x01\x00\x00\x00\x00\x00\x08\x01\x00\x00\x00")
+
+  def testHeaderBadSize(self):
+    """Verify size > max_frame_size error"""
+    self.transport.max_frame_size = 512
+    self.testGarbage(b"AMQP\x00\x01\x00\x00\x00\x00\x02\x01\x02\x00\x00\x00")
+
+  def testProtocolNotSupported(self):
+    self.transport.push(b"AMQP\x01\x01\x0a\x00")
+    p = self.transport.pending()
+    assert p >= 8, p
+    bytes = self.transport.peek(p)
+    assert bytes[:8] == b"AMQP\x00\x01\x00\x00"
+    self.transport.pop(p)
+    self.drain()
+    assert self.transport.closed
+
+  def testPeek(self):
+    out = self.transport.peek(1024)
+    assert out is not None
+
+  def testBindAfterOpen(self):
+    conn = Connection()
+    ssn = conn.session()
+    conn.open()
+    ssn.open()
+    conn.container = "test-container"
+    conn.hostname = "test-hostname"
+    trn = Transport()
+    trn.bind(conn)
+    out = trn.peek(1024)
+    assert b"test-container" in out, repr(out)
+    assert b"test-hostname" in out, repr(out)
+    self.transport.push(out)
+
+    c = Connection()
+    assert c.remote_container == None
+    assert c.remote_hostname == None
+    assert c.session_head(0) == None
+    self.transport.bind(c)
+    assert c.remote_container == "test-container"
+    assert c.remote_hostname == "test-hostname"
+    assert c.session_head(0) != None
+
+  def testCloseHead(self):
+    n = self.transport.pending()
+    assert n > 0, n
+    try:
+      self.transport.close_head()
+    except TransportException:
+      e = sys.exc_info()[1]
+      assert "aborted" in str(e), str(e)
+    n = self.transport.pending()
+    assert n < 0, n
+
+  def testCloseTail(self):
+    n = self.transport.capacity()
+    assert n > 0, n
+    try:
+      self.transport.close_tail()
+    except TransportException:
+      e = sys.exc_info()[1]
+      assert "aborted" in str(e), str(e)
+    n = self.transport.capacity()
+    assert n < 0, n
+
+  def testUnpairedPop(self):
+    conn = Connection()
+    self.transport.bind(conn)
+
+    conn.hostname = "hostname"
+    conn.open()
+
+    dat1 = self.transport.peek(1024)
+
+    ssn = conn.session()
+    ssn.open()
+
+    dat2 = self.transport.peek(1024)
+
+    assert dat2[:len(dat1)] == dat1
+
+    snd = ssn.sender("sender")
+    snd.open()
+
+    self.transport.pop(len(dat1))
+    self.transport.pop(len(dat2) - len(dat1))
+    dat3 = self.transport.peek(1024)
+    self.transport.pop(len(dat3))
+    assert self.transport.peek(1024) == b""
+
+    self.peer.push(dat1)
+    self.peer.push(dat2[len(dat1):])
+    self.peer.push(dat3)
+
+class ServerTransportTest(Test):
+
+  def setUp(self):
+    self.transport = Transport(Transport.SERVER)
+    self.peer = Transport()
+    self.conn = Connection()
+    self.peer.bind(self.conn)
+
+  def tearDOwn(self):
+    self.transport = None
+    self.peer = None
+    self.conn = None
+
+  def drain(self):
+    while True:
+      p = self.transport.pending()
+      if p < 0:
+        return
+      elif p > 0:
+        bytes = self.transport.peek(p)
+        self.peer.push(bytes)
+        self.transport.pop(len(bytes))
+      else:
+        assert False
+
+  def assert_error(self, name):
+    assert self.conn.remote_container is None, self.conn.remote_container
+    self.drain()
+    # verify that we received an open frame
+    assert self.conn.remote_container is not None, self.conn.remote_container
+    # verify that we received a close frame
+    assert self.conn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_CLOSED, self.conn.state
+    # verify that a framing error was reported
+    assert self.conn.remote_condition.name == name, self.conn.remote_condition
+
+  # TODO: This may no longer be testing anything
+  def testEOS(self):
+    self.transport.push(b"") # should be a noop
+    self.transport.close_tail()
+    p = self.transport.pending()
+    self.drain()
+    assert self.transport.closed
+
+  def testPartial(self):
+    self.transport.push(b"AMQ") # partial header
+    self.transport.close_tail()
+    p = self.transport.pending()
+    assert p >= 8, p
+    bytes = self.transport.peek(p)
+    assert bytes[:8] == b"AMQP\x00\x01\x00\x00"
+    self.transport.pop(p)
+    self.drain()
+    assert self.transport.closed
+
+  def testGarbage(self, garbage=b"GARBAGE_"):
+    self.transport.push(garbage)
+    p = self.transport.pending()
+    assert p >= 8, p
+    bytes = self.transport.peek(p)
+    assert bytes[:8] == b"AMQP\x00\x01\x00\x00"
+    self.transport.pop(p)
+    self.drain()
+    assert self.transport.closed
+
+  def testSmallGarbage(self):
+    self.testGarbage(b"XXX")
+
+  def testBigGarbage(self):
+    self.testGarbage(b"GARBAGE_XXX")
+
+  def testHeader(self):
+    self.transport.push(b"AMQP\x00\x01\x00\x00")
+    self.transport.close_tail()
+    self.assert_error(u'amqp:connection:framing-error')
+
+  def testProtocolNotSupported(self):
+    self.transport.push(b"AMQP\x01\x01\x0a\x00")
+    p = self.transport.pending()
+    assert p >= 8, p
+    bytes = self.transport.peek(p)
+    assert bytes[:8] == b"AMQP\x00\x01\x00\x00"
+    self.transport.pop(p)
+    self.drain()
+    assert self.transport.closed
+
+  def testPeek(self):
+    out = self.transport.peek(1024)
+    assert out is not None
+
+  def testBindAfterOpen(self):
+    conn = Connection()
+    ssn = conn.session()
+    conn.open()
+    ssn.open()
+    conn.container = "test-container"
+    conn.hostname = "test-hostname"
+    trn = Transport()
+    trn.bind(conn)
+    out = trn.peek(1024)
+    assert b"test-container" in out, repr(out)
+    assert b"test-hostname" in out, repr(out)
+    self.transport.push(out)
+
+    c = Connection()
+    assert c.remote_container == None
+    assert c.remote_hostname == None
+    assert c.session_head(0) == None
+    self.transport.bind(c)
+    assert c.remote_container == "test-container"
+    assert c.remote_hostname == "test-hostname"
+    assert c.session_head(0) != None
+
+  def testCloseHead(self):
+    n = self.transport.pending()
+    assert n >= 0, n
+    try:
+      self.transport.close_head()
+    except TransportException:
+      e = sys.exc_info()[1]
+      assert "aborted" in str(e), str(e)
+    n = self.transport.pending()
+    assert n < 0, n
+
+  def testCloseTail(self):
+    n = self.transport.capacity()
+    assert n > 0, n
+    try:
+      self.transport.close_tail()
+    except TransportException:
+      e = sys.exc_info()[1]
+      assert "aborted" in str(e), str(e)
+    n = self.transport.capacity()
+    assert n < 0, n
+
+  def testUnpairedPop(self):
+    conn = Connection()
+    self.transport.bind(conn)
+
+    conn.hostname = "hostname"
+    conn.open()
+
+    dat1 = self.transport.peek(1024)
+
+    ssn = conn.session()
+    ssn.open()
+
+    dat2 = self.transport.peek(1024)
+
+    assert dat2[:len(dat1)] == dat1
+
+    snd = ssn.sender("sender")
+    snd.open()
+
+    self.transport.pop(len(dat1))
+    self.transport.pop(len(dat2) - len(dat1))
+    dat3 = self.transport.peek(1024)
+    self.transport.pop(len(dat3))
+    assert self.transport.peek(1024) == b""
+
+    self.peer.push(dat1)
+    self.peer.push(dat2[len(dat1):])
+    self.peer.push(dat3)
+
+  def testEOSAfterSASL(self):
+    self.transport.sasl().allowed_mechs('ANONYMOUS')
+
+    self.peer.sasl().allowed_mechs('ANONYMOUS')
+
+    # this should send over the sasl header plus a sasl-init set up
+    # for anonymous
+    p = self.peer.pending()
+    self.transport.push(self.peer.peek(p))
+    self.peer.pop(p)
+
+    # now we send EOS
+    self.transport.close_tail()
+
+    # the server may send an error back
+    p = self.transport.pending()
+    while p>0:
+      self.peer.push(self.transport.peek(p))
+      self.transport.pop(p)
+      p = self.transport.pending()
+
+    # server closed
+    assert self.transport.pending() < 0
+
+class LogTest(Test):
+
+  def testTracer(self):
+    t = Transport()
+    assert t.tracer is None
+    messages = []
+    def tracer(transport, message):
+      messages.append((transport, message))
+    t.tracer = tracer
+    assert t.tracer is tracer
+    t.log("one")
+    t.log("two")
+    t.log("three")
+    assert messages == [(t, "one"), (t, "two"), (t, "three")], messages

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/url.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/url.py b/python/tests/proton_tests/url.py
new file mode 100644
index 0000000..b44699a
--- /dev/null
+++ b/python/tests/proton_tests/url.py
@@ -0,0 +1,147 @@
+from __future__ import absolute_import
+#
+# 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.
+#
+
+
+from . import common
+from proton import Url
+
+class UrlTest(common.Test):
+    def assertEqual(self, a, b):
+        assert a == b, "%s != %s" % (a, b)
+
+    def assertNotEqual(self, a, b):
+        assert a != b, "%s == %s" % (a, b)
+
+    def assertUrl(self, u, scheme, username, password, host, port, path):
+        self.assertEqual((u.scheme, u.username, u.password, u.host, u.port, u.path),
+                         (scheme, username, password, host, port, path))
+
+    def testUrl(self):
+        url = Url('amqp://me:secret@myhost:1234/foobar')
+        self.assertEqual(str(url), "amqp://me:secret@myhost:1234/foobar")
+        self.assertUrl(url, 'amqp', 'me', 'secret', 'myhost', 1234, 'foobar')
+        self.assertEqual(str(url), "amqp://me:secret@myhost:1234/foobar")
+
+    def testDefaults(self):
+        # Check that we allow None for scheme, port
+        url = Url(username='me', password='secret', host='myhost', path='foobar', defaults=False)
+        self.assertEqual(str(url), "//me:secret@myhost/foobar")
+        self.assertUrl(url, None, 'me', 'secret', 'myhost', None, 'foobar')
+
+        self.assertEqual(str(Url("amqp://me:secret@myhost/foobar")),
+                         "amqp://me:secret@myhost:amqp/foobar")
+
+        # Empty string vs. None for path
+        self.assertEqual(Url("myhost/").path, "")
+        assert Url("myhost", defaults=False).path is None
+
+        # Expanding abbreviated url strings.
+        for s, u in [
+            ("", "amqp://0.0.0.0:amqp"),
+            ("foo", "amqp://foo:amqp"),
+            (":1234", "amqp://0.0.0.0:1234"),
+            ("/path", "amqp://0.0.0.0:amqp/path"),
+            ("user@host/topic://test", "amqp://user@host:amqp/topic://test"),
+            ("user@host:3456", "amqp://user@host:3456"),
+            ("user:pass@host/topic://test", "amqp://user:pass@host:amqp/topic://test")
+        ]: self.assertEqual(str(Url(s)), u)
+
+    def assertPort(self, port, portint, portstr):
+        self.assertEqual((port, port), (portint, portstr))
+        self.assertEqual((int(port), str(port)), (portint, portstr))
+
+    def testPort(self):
+        self.assertPort(Url.Port('amqp'), 5672, 'amqp')
+        self.assertPort(Url.Port(5672), 5672, '5672')
+        self.assertPort(Url.Port(5671), 5671, '5671')
+        self.assertEqual(Url.Port(5671)+1, 5672) # Treat as int
+        self.assertEqual(str(Url.Port(5672)), '5672')
+
+        self.assertPort(Url.Port(Url.Port('amqp')), 5672, 'amqp')
+        self.assertPort(Url.Port(Url.Port(5672)), 5672, '5672')
+
+        try:
+            Url.Port('xxx')
+            assert False, "Expected ValueError"
+        except ValueError: pass
+
+        self.assertEqual(str(Url("host:amqp", defaults=False)), "//host:amqp")
+        self.assertEqual(Url("host:amqp", defaults=False).port, 5672)
+
+    def testArgs(self):
+        u = Url("amqp://u:p@host:amqp/path", scheme='foo', host='bar', port=1234, path='garden', defaults=False)
+        self.assertUrl(u, 'foo', 'u', 'p', 'bar', 1234, 'garden')
+        u = Url(defaults=False)
+        self.assertUrl(u, None, None, None, None, None, None)
+
+    def assertRaises(self, exception, function, *args, **kwargs):
+        try:
+            function(*args, **kwargs)
+            assert False, "Expected exception %s" % exception.__name__
+        except exception: pass
+
+    def testMissing(self):
+        self.assertUrl(Url(defaults=False), None, None, None, None, None, None)
+        self.assertUrl(Url('amqp://', defaults=False), 'amqp', None, None, None, None, None)
+        self.assertUrl(Url('username@', defaults=False), None, 'username', None, None, None, None)
+        self.assertUrl(Url(':pass@', defaults=False), None, '', 'pass', None, None, None)
+        self.assertUrl(Url('host', defaults=False), None, None, None, 'host', None, None)
+        self.assertUrl(Url(':1234', defaults=False), None, None, None, None, 1234, None)
+        self.assertUrl(Url('/path', defaults=False), None, None, None, None, None, 'path')
+
+        for s, full in [
+            ('amqp://', 'amqp://'),
+            ('username@','//username@'),
+            (':pass@', '//:pass@'),
+            (':1234', '//:1234'),
+            ('/path','/path')
+        ]:
+            self.assertEqual(str(Url(s, defaults=False)), full)
+
+        for s, full in [
+                ('amqp://', 'amqp://0.0.0.0:amqp'),
+                ('username@', 'amqp://username@0.0.0.0:amqp'),
+                (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
+                (':1234', 'amqp://0.0.0.0:1234'),
+                ('/path', 'amqp://0.0.0.0:amqp/path'),
+                ('foo/path', 'amqp://foo:amqp/path'),
+                (':1234/path', 'amqp://0.0.0.0:1234/path')
+        ]:
+            self.assertEqual(str(Url(s)), full)
+
+    def testAmqps(self):
+        # Scheme defaults
+        self.assertEqual(str(Url("me:secret@myhost/foobar")),
+                         "amqp://me:secret@myhost:amqp/foobar")
+        # Correct port for amqps vs. amqps
+        self.assertEqual(str(Url("amqps://me:secret@myhost/foobar")),
+                         "amqps://me:secret@myhost:amqps/foobar")
+
+        self.assertPort(Url.Port('amqps'), 5671, 'amqps')
+        self.assertEqual(str(Url("host:amqps", defaults=False)), "//host:amqps")
+        self.assertEqual(Url("host:amqps", defaults=False).port, 5671)
+
+    def testEqual(self):
+        self.assertEqual(Url("foo/path"), 'amqp://foo:amqp/path')
+        self.assertEqual('amqp://foo:amqp/path', Url("foo/path"))
+        self.assertEqual(Url("foo/path"), Url("foo/path"))
+        self.assertNotEqual(Url("foo/path"), 'xamqp://foo:amqp/path')
+        self.assertNotEqual('xamqp://foo:amqp/path', Url("foo/path"))
+        self.assertNotEqual(Url("foo/path"), Url("bar/path"))

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/utils.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/utils.py b/python/tests/proton_tests/utils.py
new file mode 100644
index 0000000..1f20bba
--- /dev/null
+++ b/python/tests/proton_tests/utils.py
@@ -0,0 +1,163 @@
+#
+# 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.
+#
+
+import os, time, sys
+from threading import Thread, Event
+from unittest import TestCase
+from proton_tests.common import Test, free_tcp_port
+from copy import copy
+from proton import Message, Url, generate_uuid, Array, UNDESCRIBED, Data, symbol, ConnectionException, ProtonException
+from proton.handlers import MessagingHandler
+from proton.reactor import Container
+from proton.utils import SyncRequestResponse, BlockingConnection
+from .common import Skipped, ensureCanTestExtendedSASL
+CONNECTION_PROPERTIES={u'connection': u'properties'}
+OFFERED_CAPABILITIES = Array(UNDESCRIBED, Data.SYMBOL, symbol("O_one"), symbol("O_two"), symbol("O_three"))
+DESIRED_CAPABILITIES = Array(UNDESCRIBED, Data.SYMBOL, symbol("D_one"), symbol("D_two"), symbol("D_three"))
+ANONYMOUS='ANONYMOUS'
+EXTERNAL='EXTERNAL'
+
+class EchoServer(MessagingHandler, Thread):
+    """
+    Simple echo server that echos messages to their reply-to. Runs in a thread.
+    Will only accept a single connection and shut down when that connection closes.
+    """
+
+    def __init__(self, url, timeout):
+        MessagingHandler.__init__(self)
+        Thread.__init__(self)
+        self.daemon = True
+        self.timeout = timeout
+        self.url = url
+        self.senders = {}
+        self.container = None
+        self.event = Event()
+
+    def on_start(self, event):
+        self.acceptor = event.container.listen(self.url)
+        self.container = event.container
+        self.event.set()
+
+    def on_link_opening(self, event):
+        if event.link.is_sender:
+            if event.link.remote_source and event.link.remote_source.dynamic:
+                event.link.source.address = str(generate_uuid())
+                self.senders[event.link.source.address] = event.link
+
+    def on_message(self, event):
+        m = event.message
+        sender = self.senders.get(m.reply_to)
+        if sender:
+            reply = Message(address=m.reply_to, body=m.body, correlation_id=m.correlation_id)
+            sender.send(reply)
+
+    def on_connection_closing(self, event):
+        self.acceptor.close()
+
+    def on_transport_error(self, event):
+        self.acceptor.close()
+
+    def run(self):
+        Container(self).run()
+
+    def wait(self):
+        self.event.wait(self.timeout)
+
+
+class ConnPropertiesServer(EchoServer):
+     def __init__(self, url, timeout):
+        EchoServer.__init__(self, url, timeout)
+        self.properties_received = False
+        self.offered_capabilities_received = False
+        self.desired_capabilities_received = False
+
+     def on_connection_opening(self, event):
+        conn = event.connection
+
+        if conn.remote_properties == CONNECTION_PROPERTIES:
+            self.properties_received = True
+        if conn.remote_offered_capabilities == OFFERED_CAPABILITIES:
+            self.offered_capabilities_received = True
+        if conn.remote_desired_capabilities == DESIRED_CAPABILITIES:
+            self.desired_capabilities_received = True
+
+class SyncRequestResponseTest(Test):
+    """Test SyncRequestResponse"""
+
+    def test_request_response(self):
+        ensureCanTestExtendedSASL()
+        def test(name, address="x"):
+            for i in range(5):
+                body="%s%s" % (name, i)
+                response = client.call(Message(address=address, body=body))
+                self.assertEquals(response.address, client.reply_to)
+                self.assertEquals(response.body, body)
+
+        server = EchoServer(Url(host="127.0.0.1", port=free_tcp_port()), self.timeout)
+        server.start()
+        server.wait()
+        connection = BlockingConnection(server.url, timeout=self.timeout)
+        client = SyncRequestResponse(connection)
+        try:
+            test("foo")         # Simple request/resposne
+        finally:
+            client.connection.close()
+        server.join(timeout=self.timeout)
+
+
+    def test_connection_properties(self):
+        ensureCanTestExtendedSASL()
+        server = ConnPropertiesServer(Url(host="127.0.0.1", port=free_tcp_port()), timeout=self.timeout)
+        server.start()
+        server.wait()
+        connection = BlockingConnection(server.url, timeout=self.timeout, properties=CONNECTION_PROPERTIES, offered_capabilities=OFFERED_CAPABILITIES, desired_capabilities=DESIRED_CAPABILITIES)
+        client = SyncRequestResponse(connection)
+        client.connection.close()
+        server.join(timeout=self.timeout)
+        self.assertEquals(server.properties_received, True)
+        self.assertEquals(server.offered_capabilities_received, True)
+        self.assertEquals(server.desired_capabilities_received, True)
+
+    def test_allowed_mechs_external(self):
+        # All this test does it make sure that if we pass allowed_mechs to BlockingConnection, it is actually used.
+        port = free_tcp_port()
+        server = ConnPropertiesServer(Url(host="127.0.0.1", port=port), timeout=self.timeout)
+        server.start()
+        server.wait()
+        try:
+            # This will cause an exception because we are specifying allowed_mechs as EXTERNAL. The SASL handshake will fail because the server is not setup to handle EXTERNAL
+            connection = BlockingConnection(server.url, timeout=self.timeout, properties=CONNECTION_PROPERTIES, offered_capabilities=OFFERED_CAPABILITIES, desired_capabilities=DESIRED_CAPABILITIES, allowed_mechs=EXTERNAL)
+            self.fail("Expected ConnectionException")
+        except ConnectionException as e:
+            self.assertTrue('amqp:unauthorized-access' in str(e), "expected unauthorized-access")
+        server.join(timeout=self.timeout)
+
+    def test_allowed_mechs_anonymous(self):
+        # All this test does it make sure that if we pass allowed_mechs to BlockingConnection, it is actually used.
+        server = ConnPropertiesServer(Url(host="127.0.0.1", port=free_tcp_port()), timeout=self.timeout)
+        server.start()
+        server.wait()
+        # An ANONYMOUS allowed_mechs will work, anonymous connections are allowed by ConnPropertiesServer
+        connection = BlockingConnection(server.url, timeout=self.timeout, properties=CONNECTION_PROPERTIES, offered_capabilities=OFFERED_CAPABILITIES, desired_capabilities=DESIRED_CAPABILITIES, allowed_mechs=ANONYMOUS)
+        client = SyncRequestResponse(connection)
+        client.connection.close()
+        server.join(timeout=self.timeout)
+        self.assertEquals(server.properties_received, True)
+        self.assertEquals(server.offered_capabilities_received, True)
+        self.assertEquals(server.desired_capabilities_received, True)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/tox-blacklist
----------------------------------------------------------------------
diff --git a/python/tests/tox-blacklist b/python/tests/tox-blacklist
new file mode 100644
index 0000000..3e31da8
--- /dev/null
+++ b/python/tests/tox-blacklist
@@ -0,0 +1,12 @@
+# Running *all* the python tests under tox is redundant as this is
+# already done by the python-test suite.
+# This file contains a list of the longer running tests that can be
+# skipped in order to speed up the tox test run
+
+proton_tests.soak.*
+proton_tests.engine.ServerTest.testIdleTimeout
+proton_tests.engine.ServerTest.testKeepalive
+proton_tests.messenger.IdleTimeoutTest.testIdleTimeout
+proton_tests.messenger.MessengerTest.testCreditBlockingRebalance
+proton_tests.messenger.NBMessengerTest.testCreditReplenish
+proton_tests.messenger.NBMessengerTest.testRecvBeforeSubscribe

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tox.ini.in
----------------------------------------------------------------------
diff --git a/python/tox.ini.in b/python/tox.ini.in
new file mode 100644
index 0000000..c514078
--- /dev/null
+++ b/python/tox.ini.in
@@ -0,0 +1,26 @@
+[tox]
+envlist = @TOX_ENVLIST@
+minversion = 1.4
+skipdist = True
+setupdir = @py_bin@/dist
+
+[testenv]
+usedevelop = False
+setenv =
+    VIRTUAL_ENV={envdir}
+    DEBUG=True
+passenv =
+    PKG_CONFIG_PATH
+    CFLAGS
+    SASLPASSWD
+    VALGRIND
+commands =
+    @CMAKE_SOURCE_DIR@/python/tests/proton-test '{posargs:--ignore-file=@CMAKE_SOURCE_DIR@/python/tests/tox-blacklist}'
+deps =
+    unittest2
+
+[testenv:pep8]
+commands = flake8
+
+[testenv:docs]
+commands = python setup.py build_sphinx

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/scripts/jenkins-proton-c-build.sh
----------------------------------------------------------------------
diff --git a/scripts/jenkins-proton-c-build.sh b/scripts/jenkins-proton-c-build.sh
index 8b710c1..1af4a45 100755
--- a/scripts/jenkins-proton-c-build.sh
+++ b/scripts/jenkins-proton-c-build.sh
@@ -69,7 +69,7 @@ $RUN_TOX && ctest -V -R 'python-tox-test'
 source config.sh
 
 # proton-c tests via python
-python ../tests/python/proton-test --xml=${XMLOUTPUT}
+python ../python/tests/proton-test --xml=${XMLOUTPUT}
 
 # proton-c native c-* tests
 ctest -V -R '^c-*'

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/interop-generate
----------------------------------------------------------------------
diff --git a/tests/python/interop-generate b/tests/python/interop-generate
deleted file mode 100755
index 9c360a6..0000000
--- a/tests/python/interop-generate
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-
-# Generate encoded  AMQP fragments for interop testing.
-
-import logging, optparse, os, struct, sys, time, traceback, types, cgi
-from proton import *
-
-def main(argv):
-
-    def write(data, filename):
-        f = open(filename+".amqp", 'w')
-        f.write(data.encode())
-        f.close()
-
-    # message
-    m = Message()
-    d = Data()
-    d.put_string("hello")
-    m.body = d.encode()
-    write(m, "message")
-
-    # null
-    d = Data()
-    d.put_null()
-    write(d, "null")
-
-    # primitive types
-    d = Data()
-    d.put_bool(True)
-    d.put_bool(False)
-    d.put_ubyte(42)
-    d.put_ushort(42)
-    d.put_short(-42)
-    d.put_uint(12345)
-    d.put_int(-12345)
-    d.put_ulong(12345)
-    d.put_long(-12345)
-    d.put_float(0.125)
-    d.put_double(0.125)
-    write(d, "primitives")
-
-    # string types
-    d = Data()
-    d.put_binary("abc\0defg")
-    d.put_string("abcdefg")
-    d.put_symbol("abcdefg")
-    d.put_binary("")
-    d.put_string("")
-    d.put_symbol("")
-    write(d, "strings")
-
-    # described types
-    d = Data()
-    d.put_described()
-    d.enter()
-    d.put_symbol("foo-descriptor")
-    d.put_string("foo-value")
-    d.exit()
-
-    d.put_described()
-    d.enter()
-    d.put_int(12)
-    d.put_int(13)
-    d.exit()
-
-    write(d, "described")
-
-    # described array
-    d = Data()
-    d.put_array(True, Data.INT)
-    d.enter()
-    d.put_symbol("int-array")
-    for i in xrange(0,10): d.put_int(i)
-    d.exit()
-    write(d, "described_array")
-
-
-    # Arrays
-
-    # Integer array
-    d = Data()
-    d.put_array(False, Data.INT)
-    d.enter()
-    for i in xrange(0,100): d.put_int(i)
-    d.exit()
-
-    # String array
-    d.put_array(False, Data.STRING)
-    d.enter()
-    for i in ["a", "b", "c"]: d.put_string(i)
-    d.exit()
-
-    # empty array
-    d.put_array(False, Data.INT)
-
-    write(d, "arrays")
-
-    # List - mixed types
-    d = Data()
-    d.put_list()
-    d.enter()
-    d.put_int(32)
-    d.put_string("foo")
-    d.put_bool(True)
-    d.exit()
-
-    d.put_list()                # Empty list
-    write(d, "lists")
-
-    # Maps
-    d = Data()
-    d.put_map()
-    d.enter()
-    for k,v in {"one":1, "two":2, "three":3}.items():
-        d.put_string(k)
-        d.put_int(v)
-    d.exit()
-
-    d.put_map()
-    d.enter()
-    for k,v in {1:"one", 2:"two", 3:"three"}.items():
-        d.put_int(k)
-        d.put_string(v)
-    d.exit()
-
-    d.put_map()                 # Empty map
-    write(d, "maps")
-
-    return 0
-
-if __name__ == "__main__":
-    sys.exit(main(sys.argv))

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton-test
----------------------------------------------------------------------
diff --git a/tests/python/proton-test b/tests/python/proton-test
deleted file mode 100755
index 951fea8..0000000
--- a/tests/python/proton-test
+++ /dev/null
@@ -1,711 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-
-# TODO: summarize, test harness preconditions (e.g. broker is alive)
-
-import logging, optparse, os, struct, sys, time, traceback, types, cgi
-from fnmatch import fnmatchcase as match
-from getopt import GetoptError
-from logging import getLogger, StreamHandler, Formatter, Filter, \
-    WARN, DEBUG, ERROR
-import unittest
-from proton_tests.common import SkipTest
-
-if sys.version_info[0] == 3:
-    CLASS_TYPES = (type,)
-else:
-    CLASS_TYPES = (type, types.ClassType)
-
-levels = {
-  "DEBUG": DEBUG,
-  "WARN": WARN,
-  "ERROR": ERROR
-  }
-
-sorted_levels = [(v, k) for k, v in list(levels.items())]
-sorted_levels.sort()
-sorted_levels = [v for k, v in sorted_levels]
-
-parser = optparse.OptionParser(usage="usage: %prog [options] PATTERN ...",
-                               description="Run tests matching the specified PATTERNs.")
-parser.add_option("-l", "--list", action="store_true", default=False,
-                  help="list tests instead of executing them")
-parser.add_option("-f", "--log-file", metavar="FILE", help="log output to FILE")
-parser.add_option("-v", "--log-level", metavar="LEVEL", default="WARN",
-                  help="only display log messages of LEVEL or higher severity: "
-                  "%s (default %%default)" % ", ".join(sorted_levels))
-parser.add_option("-c", "--log-category", metavar="CATEGORY", action="append",
-                  dest="log_categories", default=[],
-                  help="log only categories matching CATEGORY pattern")
-parser.add_option("-m", "--module", action="append", default=[],
-                  dest="modules", help="add module to test search path")
-parser.add_option("-i", "--ignore", action="append", default=[],
-                  help="ignore tests matching IGNORE pattern")
-parser.add_option("-I", "--ignore-file", metavar="IFILE", action="append",
-                  default=[],
-                  help="ignore tests matching patterns in IFILE")
-parser.add_option("-H", "--halt-on-error", action="store_true", default=False,
-                  dest="hoe", help="halt if an error is encountered")
-parser.add_option("-t", "--time", action="store_true", default=False,
-                  help="report timing information on test run")
-parser.add_option("-D", "--define", metavar="DEFINE", dest="defines",
-                  action="append", default=[], help="define test parameters")
-parser.add_option("-x", "--xml", metavar="XML", dest="xml",
-                  help="write test results in Junit style xml suitable for use by CI tools etc")
-parser.add_option("-a", "--always-colorize", action="store_true", dest="always_colorize", default=False,
-                  help="always colorize the test results rather than relying on terminal tty detection. Useful when invoked from Jython/Maven.")
-parser.add_option("-n", metavar="count", dest="count", type=int, default=1,
-                  help="run the tests <count> times")
-parser.add_option("-b", "--bare", action="store_true", default=False,
-                  help="Run bare, i.e. don't capture stack traces. This is useful under Jython as " +
-                  "captured stack traces do not include the Java portion of the stack," +
-                  "whereas non captured stack traces do.")
-parser.add_option("-j", "--javatrace", action="store_true", default=False,
-                  help="Show the full java stack trace. This disables heuristics to eliminate the " +
-                  "jython portion of java stack traces.")
-
-class Config:
-
-  def __init__(self):
-    self.defines = {}
-    self.log_file = None
-    self.log_level = WARN
-    self.log_categories = []
-
-opts, args = parser.parse_args()
-
-# Known bad tests, skipped unless specifically matched on the command line
-known_bad = ["proton_tests.messenger.*"]
-
-includes = []
-excludes = ["*__*__"]
-config = Config()
-list_only = opts.list
-for d in opts.defines:
-  try:
-    idx = d.index("=")
-    name = d[:idx]
-    value = d[idx+1:]
-    config.defines[name] = value
-  except ValueError:
-    config.defines[d] = None
-config.log_file = opts.log_file
-config.log_level = levels[opts.log_level.upper()]
-config.log_categories = opts.log_categories
-excludes.extend([v.strip() for v in opts.ignore])
-for v in opts.ignore_file:
-  f = open(v)
-  for line in f:
-    line = line.strip()
-    if line.startswith("#"):
-      continue
-    excludes.append(line)
-  f.close()
-
-for a in args:
-  includes.append(a.strip())
-
-def is_ignored(path):
-  for p in excludes:
-    if match(path, p):
-      return True
-  return False
-
-def is_included(path):
-  if is_ignored(path):
-    return False
-  for p in includes:
-    if match(path, p):
-      return True
-  for p in known_bad:
-    if match(path, p):
-      return False
-  return not includes           # If includes is empty, include everything
-
-def is_smart():
-  return sys.stdout.isatty() and os.environ.get("TERM", "dumb") != "dumb"
-
-try:
-  import fcntl, termios
-
-  def width():
-    if is_smart():
-      s = struct.pack("HHHH", 0, 0, 0, 0)
-      fd_stdout = sys.stdout.fileno()
-      x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s)
-      rows, cols, xpx, ypx = struct.unpack("HHHH", x)
-      return cols
-    else:
-      try:
-        return int(os.environ.get("COLUMNS", "80"))
-      except ValueError:
-        return 80
-
-  WIDTH = width()
-
-  def resize(sig, frm):
-    global WIDTH
-    WIDTH = width()
-
-  import signal
-  signal.signal(signal.SIGWINCH, resize)
-
-except ImportError:
-  WIDTH = 80
-
-def vt100_attrs(*attrs):
-  return "\x1B[%sm" % ";".join(map(str, attrs))
-
-vt100_reset = vt100_attrs(0)
-
-KEYWORDS = {"pass": (32,),
-            "skip": (33,),
-            "fail": (31,),
-            "start": (34,),
-            "total": (34,),
-            "ignored": (33,),
-            "selected": (34,),
-            "elapsed": (34,),
-            "average": (34,)}
-
-def colorize_word(word, text=None):
-  if text is None:
-    text = word
-  return colorize(text, *KEYWORDS.get(word, ()))
-
-def colorize(text, *attrs):
-  if attrs and (is_smart() or opts.always_colorize):
-    return "%s%s%s" % (vt100_attrs(*attrs), text, vt100_reset)
-  else:
-    return text
-
-def indent(text):
-  lines = text.split("\n")
-  return "  %s" % "\n  ".join(lines)
-
-# Write a 'minimal' Junit xml style report file suitable for use by CI tools such as Jenkins.
-class JunitXmlStyleReporter:
-
-  def __init__(self, file):
-    self.f = open(file, "w");
-
-  def begin(self):
-    self.f.write('<?xml version="1.0" encoding="UTF-8" ?>\n')
-    self.f.write('<testsuite name="pythontests">\n')
-
-  def report(self, name, result):
-    parts = name.split(".")
-    method = parts[-1]
-    module = '.'.join(parts[0:-1])
-    self.f.write('<testcase classname="%s" name="%s" time="%f">\n' % (module, method, result.time))
-    if result.failed:
-      escaped_type = cgi.escape(str(result.exception_type))
-      escaped_message = cgi.escape(str(result.exception_message))
-      self.f.write('<failure type="%s" message="%s">\n' % (escaped_type, escaped_message))
-      self.f.write('<![CDATA[\n')
-      self.f.write(result.formatted_exception_trace)
-      self.f.write(']]>\n')
-      self.f.write('</failure>\n')
-    if result.skipped:
-      self.f.write('<skipped/>\n')
-    self.f.write('</testcase>\n')
-
-  def end(self):
-      self.f.write('</testsuite>\n')
-      self.f.close()
-
-class Interceptor:
-
-  def __init__(self):
-    self.newline = False
-    self.indent = False
-    self.passthrough = True
-    self.dirty = False
-    self.last = None
-
-  def begin(self):
-    self.newline = True
-    self.indent = True
-    self.passthrough = False
-    self.dirty = False
-    self.last = None
-
-  def reset(self):
-    self.newline = False
-    self.indent = False
-    self.passthrough = True
-
-class StreamWrapper:
-
-  def __init__(self, interceptor, stream, prefix="  "):
-    self.interceptor = interceptor
-    self.stream = stream
-    self.prefix = prefix
-
-  def fileno(self):
-    return self.stream.fileno()
-
-  def isatty(self):
-    return self.stream.isatty()
-
-  def write(self, s):
-    if self.interceptor.passthrough:
-      self.stream.write(s)
-      return
-
-    if s:
-      self.interceptor.dirty = True
-
-    if self.interceptor.newline:
-      self.interceptor.newline = False
-      self.stream.write(" %s\n" % colorize_word("start"))
-      self.interceptor.indent = True
-    if self.interceptor.indent:
-      self.stream.write(self.prefix)
-    if s.endswith("\n"):
-      s = s.replace("\n", "\n%s" % self.prefix)[:-2]
-      self.interceptor.indent = True
-    else:
-      s = s.replace("\n", "\n%s" % self.prefix)
-      self.interceptor.indent = False
-    self.stream.write(s)
-
-    if s:
-      self.interceptor.last = s[-1]
-
-  def flush(self):
-    self.stream.flush()
-
-interceptor = Interceptor()
-
-out_wrp = StreamWrapper(interceptor, sys.stdout)
-err_wrp = StreamWrapper(interceptor, sys.stderr)
-
-out = sys.stdout
-err = sys.stderr
-sys.stdout = out_wrp
-sys.stderr = err_wrp
-
-class PatternFilter(Filter):
-
-  def __init__(self, *patterns):
-    Filter.__init__(self, patterns)
-    self.patterns = patterns
-
-  def filter(self, record):
-    if not self.patterns:
-      return True
-    for p in self.patterns:
-      if match(record.name, p):
-        return True
-    return False
-
-root = getLogger()
-handler = StreamHandler(sys.stdout)
-filter = PatternFilter(*config.log_categories)
-handler.addFilter(filter)
-handler.setFormatter(Formatter("%(asctime)s %(levelname)s %(message)s"))
-root.addHandler(handler)
-root.setLevel(WARN)
-
-log = getLogger("proton.test")
-
-PASS = "pass"
-SKIP = "skip"
-FAIL = "fail"
-
-class Runner:
-
-  def __init__(self):
-    self.exception = None
-    self.exception_phase_name = None
-    self.skip = False
-
-  def passed(self):
-    return not self.exception
-
-  def skipped(self):
-    return self.skip
-
-  def failed(self):
-    return self.exception and not self.skip
-
-  def halt(self):
-    """determines if the overall test execution should be allowed to continue to the next phase"""
-    return self.exception or self.skip
-
-  def run(self, phase_name, phase):
-    """invokes a test-phase method (which can be the test method itself or a setUp/tearDown
-       method).  If the method raises an exception the exception is examined to see if the
-       exception should be classified as a 'skipped' test"""
-    # we don't try to catch exceptions for jython because currently a
-    # jython bug will prevent the java portion of the stack being
-    # stored with the exception info in the sys module
-    if opts.bare:
-      phase()
-    else:
-      try:
-        phase()
-      except KeyboardInterrupt:
-        raise
-      except:
-        self.exception_phase_name = phase_name
-        self.exception = sys.exc_info()
-        exception_type = self.exception[0]
-        self.skip = getattr(exception_type, "skipped", False) or issubclass(exception_type, SkipTest)
-
-  def status(self):
-    if self.passed():
-      return PASS
-    elif self.skipped():
-      return SKIP
-    elif self.failed():
-      return FAIL
-    else:
-      return None
-
-  def get_formatted_exception_trace(self):
-    if self.exception:
-      if self.skip:
-        # format skipped tests without a traceback
-        output = indent("".join(traceback.format_exception_only(*self.exception[:2]))).rstrip()
-      else:
-        output = "Error during %s:" % self.exception_phase_name
-        lines = traceback.format_exception(*self.exception)
-        val = self.exception[1]
-        reflect = False
-        if val and hasattr(val, "getStackTrace"):
-          jlines = []
-          for frame in val.getStackTrace():
-            if reflect and frame.getClassName().startswith("org.python."):
-              # this is a heuristic to eliminate the jython portion of
-              # the java stack trace
-              if not opts.javatrace:
-                break
-            jlines.append("  %s\n" % frame.toString())
-            if frame.getClassName().startswith("java.lang.reflect"):
-              reflect = True
-            else:
-              reflect = False
-          lines.extend(jlines)
-        output += indent("".join(lines)).rstrip()
-      return output
-
-  def get_exception_type(self):
-    if self.exception:
-      return self.exception[0]
-    else:
-      return None
-
-  def get_exception_message(self):
-    if self.exception:
-      return self.exception[1]
-    else:
-      return None
-
-ST_WIDTH = 8
-
-def run_test(name, test, config):
-  patterns = filter.patterns
-  level = root.level
-  filter.patterns = config.log_categories
-  root.setLevel(config.log_level)
-
-  parts = name.split(".")
-  line = None
-  output = ""
-  for part in parts:
-    if line:
-      if len(line) + len(part) >= (WIDTH - ST_WIDTH - 1):
-        output += "%s. \\\n" % line
-        line = "    %s" % part
-      else:
-        line = "%s.%s" % (line, part)
-    else:
-      line = part
-
-  if line:
-    output += "%s %s" % (line, (((WIDTH - ST_WIDTH) - len(line))*"."))
-  sys.stdout.write(output)
-  sys.stdout.flush()
-  interceptor.begin()
-  start = time.time()
-  try:
-    runner = test()
-  finally:
-    interceptor.reset()
-  end = time.time()
-  if interceptor.dirty:
-    if interceptor.last != "\n":
-      sys.stdout.write("\n")
-    sys.stdout.write(output)
-  print(" %s" % colorize_word(runner.status()))
-  if runner.failed() or runner.skipped():
-    print(runner.get_formatted_exception_trace())
-  root.setLevel(level)
-  filter.patterns = patterns
-  return TestResult(end - start,
-                    runner.passed(),
-                    runner.skipped(),
-                    runner.failed(),
-                    runner.get_exception_type(),
-                    runner.get_exception_message(),
-                    runner.get_formatted_exception_trace())
-
-class TestResult:
-
-  def __init__(self, time, passed, skipped, failed, exception_type, exception_message, formatted_exception_trace):
-    self.time = time
-    self.passed = passed
-    self.skipped = skipped
-    self.failed = failed
-    self.exception_type =  exception_type
-    self.exception_message = exception_message
-    self.formatted_exception_trace = formatted_exception_trace
-
-class FunctionTest:
-
-  def __init__(self, test):
-    self.test = test
-
-  def name(self):
-    return "%s.%s" % (self.test.__module__, self.test.__name__)
-
-  def run(self):
-    return run_test(self.name(), self._run, config)
-
-  def _run(self):
-    runner = Runner()
-    runner.run("test", lambda: self.test(config))
-    return runner
-
-  def __repr__(self):
-    return "FunctionTest(%r)" % self.test
-
-class MethodTest:
-
-  def __init__(self, cls, method):
-    self.cls = cls
-    self.method = method
-
-  def name(self):
-    return "%s.%s.%s" % (self.cls.__module__, self.cls.__name__, self.method)
-
-  def run(self):
-    return run_test(self.name(), self._run, config)
-
-  def _run(self):
-    runner = Runner()
-    inst = self.cls(self.method)
-    test = getattr(inst, self.method)
-
-    if hasattr(inst, "configure"):
-      runner.run("configure", lambda: inst.configure(config))
-      if runner.halt(): return runner
-    if hasattr(inst, "setUp"):
-      runner.run("setup", inst.setUp)
-      if runner.halt(): return runner
-
-    runner.run("test", test)
-
-    if hasattr(inst, "tearDown"):
-      runner.run("teardown", inst.tearDown)
-
-    return runner
-
-  def __repr__(self):
-    return "MethodTest(%r, %r)" % (self.cls, self.method)
-
-class PatternMatcher:
-
-  def __init__(self, *patterns):
-    self.patterns = patterns
-
-  def matches(self, name):
-    for p in self.patterns:
-      if match(name, p):
-        return True
-    return False
-
-class FunctionScanner(PatternMatcher):
-
-  def inspect(self, obj):
-    return type(obj) == types.FunctionType and self.matches(obj.__name__)
-
-  def descend(self, func):
-    # the None is required for older versions of python
-    return; yield None
-
-  def extract(self, func):
-    yield FunctionTest(func)
-
-class ClassScanner(PatternMatcher):
-
-  def inspect(self, obj):
-    return type(obj) in CLASS_TYPES and self.matches(obj.__name__)
-
-  def descend(self, cls):
-    # the None is required for older versions of python
-    return; yield None
-
-  def extract(self, cls):
-    names = dir(cls)
-    names.sort()
-    for name in names:
-      obj = getattr(cls, name)
-      if hasattr(obj, '__call__') and name.startswith("test"):
-        yield MethodTest(cls, name)
-
-class ModuleScanner:
-
-  def inspect(self, obj):
-    return type(obj) == types.ModuleType
-
-  def descend(self, obj):
-    names = dir(obj)
-    names.sort()
-    for name in names:
-      yield getattr(obj, name)
-
-  def extract(self, obj):
-    # the None is required for older versions of python
-    return; yield None
-
-class Harness:
-
-  def __init__(self):
-    self.scanners = [
-      ModuleScanner(),
-      ClassScanner("*Test", "*Tests", "*TestCase"),
-      FunctionScanner("test_*")
-      ]
-    self.tests = []
-    self.scanned = []
-
-  def scan(self, *roots):
-    objects = list(roots)
-
-    while objects:
-      obj = objects.pop(0)
-      for s in self.scanners:
-        if s.inspect(obj):
-          self.tests.extend(s.extract(obj))
-          for child in s.descend(obj):
-            if not (child in self.scanned or child in objects):
-              objects.append(child)
-      self.scanned.append(obj)
-
-modules = opts.modules
-if not modules:
-  modules.extend(["proton_tests"])
-h = Harness()
-for name in modules:
-  m = __import__(name, None, None, ["dummy"])
-  h.scan(m)
-
-filtered = [t for t in h.tests if is_included(t.name())]
-ignored = [t for t in h.tests if is_ignored(t.name())]
-total = len(filtered) + len(ignored)
-
-if opts.xml and not list_only:
-   xmlr = JunitXmlStyleReporter(opts.xml);
-   xmlr.begin();
-else:
-   xmlr = None
-
-def runthrough():
-  passed = 0
-  failed = 0
-  skipped = 0
-  start = time.time()
-  for t in filtered:
-    if list_only:
-      print(t.name())
-    else:
-      st = t.run()
-      if xmlr:
-        xmlr.report(t.name(), st)
-      if st.passed:
-        passed += 1
-      elif st.skipped:
-        skipped += 1
-      elif st.failed:
-        failed += 1
-        if opts.hoe:
-          break
-  end = time.time()
-
-  run = passed + failed
-
-  if not list_only:
-    if passed:
-      _pass = "pass"
-    else:
-      _pass = "fail"
-    if failed:
-      outcome = "fail"
-    else:
-      outcome = "pass"
-    if ignored:
-      ign = "ignored"
-    else:
-      ign = "pass"
-    if skipped:
-      skip = "skip"
-    else:
-      skip = "pass"
-    sys.stdout.write(colorize("Totals: ", 1))
-    totals = [colorize_word("total", "%s tests" % total),
-              colorize_word(_pass, "%s passed" % passed),
-              colorize_word(skip, "%s skipped" % skipped),
-              colorize_word(ign, "%s ignored" % len(ignored)),
-              colorize_word(outcome, "%s failed" % failed)]
-    sys.stdout.write(", ".join(totals))
-    if opts.hoe and failed > 0:
-      print(" -- (halted after %s)" % run)
-    else:
-      print("")
-    if opts.time and run > 0:
-      sys.stdout.write(colorize("Timing:", 1))
-      timing = [colorize_word("elapsed", "%.2fs elapsed" % (end - start)),
-                colorize_word("average", "%.2fs average" % ((end - start)/run))]
-      print(", ".join(timing))
-
-  if xmlr:
-     xmlr.end()
-
-  return failed
-
-limit = opts.count
-count = 0
-failures = False
-while limit == 0 or count < limit:
-  count += 1
-  if runthrough():
-    failures = True
-    if count > 1:
-      print(" -- (failures after %s runthroughs)" % count)
-  else:
-    continue
-
-if failures:
-  sys.exit(1)
-else:
-  sys.exit(0)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/__init__.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/__init__.py b/tests/python/proton_tests/__init__.py
deleted file mode 100644
index 66792f5..0000000
--- a/tests/python/proton_tests/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-#   http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-import proton_tests.codec
-import proton_tests.engine
-import proton_tests.message
-import proton_tests.handler
-import proton_tests.reactor
-import proton_tests.sasl
-import proton_tests.transport
-import proton_tests.ssl
-import proton_tests.interop
-import proton_tests.soak
-import proton_tests.url
-import proton_tests.utils

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/codec.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/codec.py b/tests/python/proton_tests/codec.py
deleted file mode 100644
index e13dcfe..0000000
--- a/tests/python/proton_tests/codec.py
+++ /dev/null
@@ -1,401 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-#   http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-import os, sys
-from . import common
-from proton import *
-from proton._compat import raise_
-from uuid import uuid4
-
-class Test(common.Test):
-
-  def setUp(self):
-    self.data = Data()
-
-  def tearDown(self):
-    self.data = None
-
-class DataTest(Test):
-
-  def testTopLevelNext(self):
-    assert self.data.next() is None
-    self.data.put_null()
-    self.data.put_bool(False)
-    self.data.put_int(0)
-    assert self.data.next() is None
-    self.data.rewind()
-    assert self.data.next() == Data.NULL
-    assert self.data.next() == Data.BOOL
-    assert self.data.next() == Data.INT
-    assert self.data.next() is None
-
-  def testNestedNext(self):
-    assert self.data.next() is None
-    self.data.put_null()
-    assert self.data.next() is None
-    self.data.put_list()
-    assert self.data.next() is None
-    self.data.put_bool(False)
-    assert self.data.next() is None
-    self.data.rewind()
-    assert self.data.next() is Data.NULL
-    assert self.data.next() is Data.LIST
-    self.data.enter()
-    assert self.data.next() is None
-    self.data.put_ubyte(0)
-    assert self.data.next() is None
-    self.data.put_uint(0)
-    assert self.data.next() is None
-    self.data.put_int(0)
-    assert self.data.next() is None
-    self.data.exit()
-    assert self.data.next() is Data.BOOL
-    assert self.data.next() is None
-
-    self.data.rewind()
-    assert self.data.next() is Data.NULL
-    assert self.data.next() is Data.LIST
-    assert self.data.enter()
-    assert self.data.next() is Data.UBYTE
-    assert self.data.next() is Data.UINT
-    assert self.data.next() is Data.INT
-    assert self.data.next() is None
-    assert self.data.exit()
-    assert self.data.next() is Data.BOOL
-    assert self.data.next() is None
-
-  def testEnterExit(self):
-    assert self.data.next() is None
-    assert not self.data.enter()
-    self.data.put_list()
-    assert self.data.enter()
-    assert self.data.next() is None
-    self.data.put_list()
-    assert self.data.enter()
-    self.data.put_list()
-    assert self.data.enter()
-    assert self.data.exit()
-    assert self.data.get_list() == 0
-    assert self.data.exit()
-    assert self.data.get_list() == 1
-    assert self.data.exit()
-    assert self.data.get_list() == 1
-    assert not self.data.exit()
-    assert self.data.get_list() == 1
-    assert self.data.next() is None
-
-    self.data.rewind()
-    assert self.data.next() is Data.LIST
-    assert self.data.get_list() == 1
-    assert self.data.enter()
-    assert self.data.next() is Data.LIST
-    assert self.data.get_list() == 1
-    assert self.data.enter()
-    assert self.data.next() is Data.LIST
-    assert self.data.get_list() == 0
-    assert self.data.enter()
-    assert self.data.next() is None
-    assert self.data.exit()
-    assert self.data.get_list() == 0
-    assert self.data.exit()
-    assert self.data.get_list() == 1
-    assert self.data.exit()
-    assert self.data.get_list() == 1
-    assert not self.data.exit()
-
-
-  def put(self, putter, v):
-    """More informative exception from putters, include bad value"""
-    try:
-      putter(v)
-    except Exception:
-      etype, value, trace = sys.exc_info()
-      raise_(etype, etype("%s(%r): %s" % (putter.__name__, v, value)), trace)
-    return putter
-
-  # (bits, signed) for each integer type
-  INT_TYPES = {
-    "byte": (8, True),
-    "ubyte": (8, False),
-    "short": (16, True),
-    "ushort": (16, False),
-    "int": (32, True),
-    "uint": (32, False),
-    "long": (64, True),
-    "ulong": (64, False)
-  }
-
-  def int_values(self, dtype):
-    """Set of test values for integer type dtype, include extreme and medial values"""
-    bits, signed = self.INT_TYPES[dtype]
-    values = [0, 1, 2, 5, 42]
-    if signed:
-      min, max = -2**(bits-1), 2**(bits-1)-1
-      values.append(max // 2)
-      values += [-i for i in values if i]
-      values += [min, max]
-    else:
-      max = 2**(bits) - 1
-      values += [max // 2, max]
-    return sorted(values)
-
-  def _testArray(self, dtype, descriptor, atype, *values):
-    if dtype: dTYPE = getattr(self.data, dtype.upper())
-    aTYPE = getattr(self.data, atype.upper())
-    self.data.put_array(dtype is not None, aTYPE)
-    self.data.enter()
-    if dtype is not None:
-      putter = getattr(self.data, "put_%s" % dtype)
-      self.put(putter, descriptor)
-    putter = getattr(self.data, "put_%s" % atype)
-    for v in values:
-      self.put(putter, v)
-    self.data.exit()
-    self.data.rewind()
-    assert self.data.next() == Data.ARRAY
-    count, described, type = self.data.get_array()
-    assert count == len(values), count
-    if dtype is None:
-      assert described == False
-    else:
-      assert described == True
-    assert type == aTYPE, type
-    assert self.data.enter()
-    if described:
-      assert self.data.next() == dTYPE
-      getter = getattr(self.data, "get_%s" % dtype)
-      gotten = getter()
-      assert gotten == descriptor, gotten
-    if values:
-      getter = getattr(self.data, "get_%s" % atype)
-      for v in values:
-        assert self.data.next() == aTYPE
-        gotten = getter()
-        assert gotten == v, gotten
-    assert self.data.next() is None
-    assert self.data.exit()
-
-  def testStringArray(self):
-    self._testArray(None, None, "string", "one", "two", "three")
-
-  def testDescribedStringArray(self):
-    self._testArray("symbol", "url", "string", "one", "two", "three")
-
-  def _test_int_array(self, atype):
-    self._testArray(None, None, atype, *self.int_values(atype))
-
-  def testByteArray(self): self._test_int_array("byte")
-  def testUbyteArray(self): self._test_int_array("ubyte")
-  def testShortArray(self): self._test_int_array("short")
-  def testUshortArray(self): self._test_int_array("ushort")
-  def testIntArray(self): self._test_int_array("int")
-  def testUintArray(self): self._test_int_array("uint")
-  def testLongArray(self): self._test_int_array("long")
-  def testUlongArray(self): self._test_int_array("ulong")
-
-  def testUUIDArray(self):
-    self._testArray(None, None, "uuid", uuid4(), uuid4(), uuid4())
-
-  def testEmptyArray(self):
-    self._testArray(None, None, "null")
-
-  def testDescribedEmptyArray(self):
-    self._testArray("long", 0, "null")
-
-  def _test(self, dtype, *values, **kwargs):
-    eq=kwargs.get("eq", lambda x, y: x == y)
-    ntype = getattr(Data, dtype.upper())
-    putter = getattr(self.data, "put_%s" % dtype)
-    getter = getattr(self.data, "get_%s" % dtype)
-
-    for v in values:
-      self.put(putter, v)
-      gotten = getter()
-      assert eq(gotten, v), (gotten, v)
-
-    self.data.rewind()
-
-    for v in values:
-      vtype = self.data.next()
-      assert vtype == ntype, vtype
-      gotten = getter()
-      assert eq(gotten, v), (gotten, v)
-
-    encoded = self.data.encode()
-    copy = Data(0)
-    while encoded:
-      n = copy.decode(encoded)
-      encoded = encoded[n:]
-    copy.rewind()
-
-    cgetter = getattr(copy, "get_%s" % dtype)
-
-    for v in values:
-      vtype = copy.next()
-      assert vtype == ntype, vtype
-      gotten = cgetter()
-      assert eq(gotten, v), (gotten, v)
-
-  def _test_int(self, itype):
-    self._test(itype, *self.int_values(itype))
-
-  def testByte(self): self._test_int("byte")
-  def testUbyte(self): self._test_int("ubyte")
-  def testShort(self): self._test_int("short")
-  def testUshort(self): self._test("ushort")
-  def testInt(self): self._test_int("int")
-  def testUint(self): self._test_int("uint")
-  def testLong(self): self._test_int("long")
-  def testUlong(self): self._test_int("ulong")
-
-  def testString(self):
-    self._test("string", "one", "two", "three", "this is a test", "")
-
-  def testFloat(self):
-    # we have to use a special comparison here because python
-    # internally only uses doubles and converting between floats and
-    # doubles is imprecise
-    self._test("float", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3,
-               eq=lambda x, y: x - y < 0.000001)
-
-  def testDouble(self):
-    self._test("double", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3)
-
-  def testBinary(self):
-    self._test("binary", b"this", b"is", b"a", b"test",b"of" b"b\x00inary")
-
-  def testSymbol(self):
-    self._test("symbol", symbol("this is a symbol test"), symbol("bleh"), symbol("blah"))
-
-  def testTimestamp(self):
-    self._test("timestamp", timestamp(0), timestamp(12345), timestamp(1000000))
-
-  def testChar(self):
-    self._test("char", char('a'), char('b'), char('c'), char(u'\u20AC'))
-
-  def testUUID(self):
-    self._test("uuid", uuid4(), uuid4(), uuid4())
-
-  def testDecimal32(self):
-    self._test("decimal32", decimal32(0), decimal32(1), decimal32(2), decimal32(3), decimal32(4), decimal32(2**30))
-
-  def testDecimal64(self):
-    self._test("decimal64", decimal64(0), decimal64(1), decimal64(2), decimal64(3), decimal64(4), decimal64(2**60))
-
-  def testDecimal128(self):
-    self._test("decimal128", decimal128(b"fdsaasdf;lkjjkl;"), decimal128(b"x"*16))
-
-  def testCopy(self):
-    self.data.put_described()
-    self.data.enter()
-    self.data.put_ulong(123)
-    self.data.put_map()
-    self.data.enter()
-    self.data.put_string("pi")
-    self.data.put_double(3.14159265359)
-
-    dst = Data()
-    dst.copy(self.data)
-
-    copy = dst.format()
-    orig = self.data.format()
-    assert copy == orig, (copy, orig)
-
-  def testCopyNested(self):
-    nested = [1, 2, 3, [4, 5, 6], 7, 8, 9]
-    self.data.put_object(nested)
-    dst = Data()
-    dst.copy(self.data)
-    assert dst.format() == self.data.format()
-
-  def testCopyNestedArray(self):
-    nested = [Array(UNDESCRIBED, Data.LIST,
-                    ["first", [Array(UNDESCRIBED, Data.INT, 1,2,3)]],
-                    ["second", [Array(UNDESCRIBED, Data.INT, 1,2,3)]],
-                    ["third", [Array(UNDESCRIBED, Data.INT, 1,2,3)]],
-                    ),
-              "end"]
-    self.data.put_object(nested)
-    dst = Data()
-    dst.copy(self.data)
-    assert dst.format() == self.data.format()
-
-  def testRoundTrip(self):
-    obj = {symbol("key"): timestamp(1234),
-           ulong(123): "blah",
-           char("c"): "bleh",
-           u"desc": Described(symbol("url"), u"http://example.org"),
-           u"array": Array(UNDESCRIBED, Data.INT, 1, 2, 3),
-           u"list": [1, 2, 3, None, 4],
-           u"boolean": True}
-    self.data.put_object(obj)
-    enc = self.data.encode()
-    data = Data()
-    data.decode(enc)
-    data.rewind()
-    assert data.next()
-    copy = data.get_object()
-    assert copy == obj, (copy, obj)
-
-  def testBuffer(self):
-    try:
-      self.data.put_object(buffer(b"foo"))
-    except NameError:
-      # python >= 3.0 does not have `buffer`
-      return
-    data = Data()
-    data.decode(self.data.encode())
-    data.rewind()
-    assert data.next()
-    assert data.type() == Data.BINARY
-    assert data.get_object() == b"foo"
-
-  def testMemoryView(self):
-    try:
-      self.data.put_object(memoryview(b"foo"))
-    except NameError:
-      # python <= 2.6 does not have `memoryview`
-      return
-    data = Data()
-    data.decode(self.data.encode())
-    data.rewind()
-    assert data.next()
-    assert data.type() == Data.BINARY
-    assert data.get_object() == b"foo"
-
-  def testLookup(self):
-    obj = {symbol("key"): u"value",
-           symbol("pi"): 3.14159,
-           symbol("list"): [1, 2, 3, 4]}
-    self.data.put_object(obj)
-    self.data.rewind()
-    self.data.next()
-    self.data.enter()
-    self.data.narrow()
-    assert self.data.lookup("pi")
-    assert self.data.get_object() == 3.14159
-    self.data.rewind()
-    assert self.data.lookup("key")
-    assert self.data.get_object() == u"value"
-    self.data.rewind()
-    assert self.data.lookup("list")
-    assert self.data.get_object() == [1, 2, 3, 4]
-    self.data.widen()
-    self.data.rewind()
-    assert not self.data.lookup("pi")

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/common.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/common.py b/tests/python/proton_tests/common.py
deleted file mode 100644
index 90ba34c..0000000
--- a/tests/python/proton_tests/common.py
+++ /dev/null
@@ -1,510 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-from unittest import TestCase
-try:
-  from unittest import SkipTest
-except:
-  try:
-    from unittest2 import SkipTest
-  except:
-    class SkipTest(Exception):
-      pass
-
-from random import randint
-from threading import Thread
-from socket import socket, AF_INET, SOCK_STREAM
-from subprocess import Popen,PIPE,STDOUT
-import sys, os, subprocess
-from proton import SASL, SSL
-from proton.reactor import Container
-from proton.handlers import Handshaker, FlowController
-from string import Template
-
-def free_tcp_ports(count=1):
-  """ return a list of 'count' TCP ports that are free to used (ie. unbound)
-  """
-  retry = 0
-  ports = []
-  sockets = []
-  while len(ports) != count:
-    port = randint(49152, 65535)
-    sockets.append( socket( AF_INET, SOCK_STREAM ) )
-    try:
-      sockets[-1].bind( ("0.0.0.0", port ) )
-      ports.append( port )
-      retry = 0
-    except:
-      retry += 1
-      assert retry != 100, "No free sockets available for test!"
-  for s in sockets:
-    s.close()
-  return ports
-
-def free_tcp_port():
-  return free_tcp_ports(1)[0]
-
-def pump_uni(src, dst, buffer_size=1024):
-  p = src.pending()
-  c = dst.capacity()
-
-  if c < 0:
-    if p < 0:
-      return False
-    else:
-      src.close_head()
-      return True
-
-  if p < 0:
-    dst.close_tail()
-  elif p == 0 or c == 0:
-    return False
-  else:
-    binary = src.peek(min(c, buffer_size))
-    dst.push(binary)
-    src.pop(len(binary))
-
-  return True
-
-def pump(transport1, transport2, buffer_size=1024):
-  """ Transfer all pending bytes between two Proton engines
-      by repeatedly calling peek/pop and push.
-      Asserts that each engine accepts some bytes every time
-      (unless it's already closed).
-  """
-  while (pump_uni(transport1, transport2, buffer_size) or
-         pump_uni(transport2, transport1, buffer_size)):
-    pass
-
-def findfileinpath(filename, searchpath):
-    """Find filename in the searchpath
-        return absolute path to the file or None
-    """
-    paths = searchpath.split(os.pathsep)
-    for path in paths:
-        if os.path.exists(os.path.join(path, filename)):
-            return os.path.abspath(os.path.join(path, filename))
-    return None
-
-def isSSLPresent():
-    return SSL.present()
-
-createdSASLDb = False
-
-def _cyrusSetup(conf_dir):
-  """Write out simple SASL config.
-  """
-  saslpasswd = ""
-  if 'SASLPASSWD' in os.environ:
-    saslpasswd = os.environ['SASLPASSWD']
-  else:
-    saslpasswd = findfileinpath('saslpasswd2', os.getenv('PATH')) or ""
-  if os.path.exists(saslpasswd):
-    t = Template("""sasldb_path: ${db}
-mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS
-""")
-    abs_conf_dir = os.path.abspath(conf_dir)
-    subprocess.call(args=['rm','-rf',abs_conf_dir])
-    os.mkdir(abs_conf_dir)
-    db = os.path.join(abs_conf_dir,'proton.sasldb')
-    conf = os.path.join(abs_conf_dir,'proton-server.conf')
-    f = open(conf, 'w')
-    f.write(t.substitute(db=db))
-    f.close()
-
-    cmd_template = Template("echo password | ${saslpasswd} -c -p -f ${db} -u proton user")
-    cmd = cmd_template.substitute(db=db, saslpasswd=saslpasswd)
-    subprocess.call(args=cmd, shell=True)
-
-    os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir
-    global createdSASLDb
-    createdSASLDb = True
-
-# Globally initialize Cyrus SASL configuration
-if SASL.extended():
-  _cyrusSetup('sasl-conf')
-
-def ensureCanTestExtendedSASL():
-  if not SASL.extended():
-    raise Skipped('Extended SASL not supported')
-  if not createdSASLDb:
-    raise Skipped("Can't Test Extended SASL: Couldn't create auth db")
-
-class DefaultConfig:
-    defines = {}
-
-class Test(TestCase):
-  config = DefaultConfig()
-
-  def __init__(self, name):
-    super(Test, self).__init__(name)
-    self.name = name
-
-  def configure(self, config):
-    self.config = config
-
-  def default(self, name, value, **profiles):
-    default = value
-    profile = self.config.defines.get("profile")
-    if profile:
-      default = profiles.get(profile, default)
-    return self.config.defines.get(name, default)
-
-  @property
-  def delay(self):
-    return float(self.default("delay", "1", fast="0.1"))
-
-  @property
-  def timeout(self):
-    return float(self.default("timeout", "60", fast="10"))
-
-  @property
-  def verbose(self):
-    return int(self.default("verbose", 0))
-
-
-class Skipped(SkipTest):
-  skipped = True
-
-
-class TestServer(object):
-  """ Base class for creating test-specific message servers.
-  """
-  def __init__(self, **kwargs):
-    self.args = kwargs
-    self.reactor = Container(self)
-    self.host = "127.0.0.1"
-    self.port = 0
-    if "host" in kwargs:
-      self.host = kwargs["host"]
-    if "port" in kwargs:
-      self.port = kwargs["port"]
-    self.handlers = [FlowController(10), Handshaker()]
-    self.thread = Thread(name="server-thread", target=self.run)
-    self.thread.daemon = True
-    self.running = True
-    self.conditions = []
-
-  def start(self):
-    self.reactor.start()
-    retry = 0
-    if self.port == 0:
-      self.port = str(randint(49152, 65535))
-      retry = 10
-    while retry > 0:
-      try:
-        self.acceptor = self.reactor.acceptor(self.host, self.port)
-        break
-      except IOError:
-        self.port = str(randint(49152, 65535))
-        retry -= 1
-    assert retry > 0, "No free port for server to listen on!"
-    self.thread.start()
-
-  def stop(self):
-    self.running = False
-    self.reactor.wakeup()
-    self.thread.join()
-
-  # Note: all following methods all run under the thread:
-
-  def run(self):
-    self.reactor.timeout = 3.14159265359
-    while self.reactor.process():
-      if not self.running:
-        self.acceptor.close()
-        self.reactor.stop()
-        break
-
-  def on_connection_bound(self, event):
-    if "idle_timeout" in self.args:
-      event.transport.idle_timeout = self.args["idle_timeout"]
-
-  def on_connection_local_close(self, event):
-    self.conditions.append(event.connection.condition)
-
-  def on_delivery(self, event):
-    event.delivery.settle()
-
-#
-# Classes that wrap the messenger applications msgr-send and msgr-recv.
-# These applications reside in the c/tools directory
-#
-
-class MessengerApp(object):
-    """ Interface to control a MessengerApp """
-    def __init__(self):
-        self._cmdline = None
-        # options common to Receivers and Senders:
-        self.ca_db = None
-        self.certificate = None
-        self.privatekey = None
-        self.password = None
-        self._output = None
-
-    def start(self, verbose=False):
-        """ Begin executing the test """
-        cmd = self.cmdline()
-        self._verbose = verbose
-        if self._verbose:
-            print("COMMAND='%s'" % str(cmd))
-        #print("ENV='%s'" % str(os.environ.copy()))
-        try:
-            # Handle python launch by replacing script 'filename' with
-            # 'python abspath-to-filename' in cmdline arg list.
-            if cmd[0].endswith('.py'):
-                foundfile = findfileinpath(cmd[0], os.getenv('PATH'))
-                if foundfile is None:
-                    msg = "Unable to locate file '%s' in PATH" % cmd[0]
-                    raise Skipped("Skipping test - %s" % msg)
-
-                del cmd[0:1]
-                cmd.insert(0, foundfile)
-                cmd.insert(0, sys.executable)
-            self._process = Popen(cmd, stdout=PIPE, stderr=STDOUT,
-                                  bufsize=4096, universal_newlines=True)
-        except OSError:
-            e = sys.exc_info()[1]
-            print("ERROR: '%s'" % e)
-            msg = "Unable to execute command '%s', is it in your PATH?" % cmd[0]
-
-            # NOTE(flaper87): Skip the test if the command is not found.
-            if e.errno == 2:
-              raise Skipped("Skipping test - %s" % msg)
-            assert False, msg
-
-        self._ready()  # wait for it to initialize
-
-    def stop(self):
-        """ Signal the client to start clean shutdown """
-        pass
-
-    def wait(self):
-        """ Wait for client to complete """
-        self._output = self._process.communicate()
-        if self._verbose:
-            print("OUTPUT='%s'" % self.stdout())
-
-    def status(self):
-        """ Return status from client process """
-        return self._process.returncode
-
-    def stdout(self):
-        #self._process.communicate()[0]
-        if not self._output or not self._output[0]:
-            return "*** NO STDOUT ***"
-        return self._output[0]
-
-    def stderr(self):
-        if not self._output or not self._output[1]:
-            return "*** NO STDERR ***"
-        return self._output[1]
-
-    def cmdline(self):
-        if not self._cmdline:
-            self._build_command()
-        return self._cmdline
-
-    def _build_command(self):
-        assert False, "_build_command() needs override"
-
-    def _ready(self):
-        assert False, "_ready() needs override"
-
-    def _do_common_options(self):
-        """ Common option handling """
-        if self.ca_db is not None:
-            self._cmdline.append("-T")
-            self._cmdline.append(str(self.ca_db))
-        if self.certificate is not None:
-            self._cmdline.append("-C")
-            self._cmdline.append(str(self.certificate))
-        if self.privatekey is not None:
-            self._cmdline.append("-K")
-            self._cmdline.append(str(self.privatekey))
-        if self.password is not None:
-            self._cmdline.append("-P")
-            self._cmdline.append("pass:" + str(self.password))
-
-
-class MessengerSender(MessengerApp):
-    """ Interface to configure a sending MessengerApp """
-    def __init__(self):
-        MessengerApp.__init__(self)
-        self._command = None
-        # @todo make these properties
-        self.targets = []
-        self.send_count = None
-        self.msg_size = None
-        self.send_batch = None
-        self.outgoing_window = None
-        self.report_interval = None
-        self.get_reply = False
-        self.timeout = None
-        self.incoming_window = None
-        self.recv_count = None
-        self.name = None
-
-    # command string?
-    def _build_command(self):
-        self._cmdline = self._command
-        self._do_common_options()
-        assert self.targets, "Missing targets, required for sender!"
-        self._cmdline.append("-a")
-        self._cmdline.append(",".join(self.targets))
-        if self.send_count is not None:
-            self._cmdline.append("-c")
-            self._cmdline.append(str(self.send_count))
-        if self.msg_size is not None:
-            self._cmdline.append("-b")
-            self._cmdline.append(str(self.msg_size))
-        if self.send_batch is not None:
-            self._cmdline.append("-p")
-            self._cmdline.append(str(self.send_batch))
-        if self.outgoing_window is not None:
-            self._cmdline.append("-w")
-            self._cmdline.append(str(self.outgoing_window))
-        if self.report_interval is not None:
-            self._cmdline.append("-e")
-            self._cmdline.append(str(self.report_interval))
-        if self.get_reply:
-            self._cmdline.append("-R")
-        if self.timeout is not None:
-            self._cmdline.append("-t")
-            self._cmdline.append(str(self.timeout))
-        if self.incoming_window is not None:
-            self._cmdline.append("-W")
-            self._cmdline.append(str(self.incoming_window))
-        if self.recv_count is not None:
-            self._cmdline.append("-B")
-            self._cmdline.append(str(self.recv_count))
-        if self.name is not None:
-            self._cmdline.append("-N")
-            self._cmdline.append(str(self.name))
-
-    def _ready(self):
-        pass
-
-
-class MessengerReceiver(MessengerApp):
-    """ Interface to configure a receiving MessengerApp """
-    def __init__(self):
-        MessengerApp.__init__(self)
-        self._command = None
-        # @todo make these properties
-        self.subscriptions = []
-        self.receive_count = None
-        self.recv_count = None
-        self.incoming_window = None
-        self.timeout = None
-        self.report_interval = None
-        self.send_reply = False
-        self.outgoing_window = None
-        self.forwards = []
-        self.name = None
-
-    # command string?
-    def _build_command(self):
-        self._cmdline = self._command
-        self._do_common_options()
-        self._cmdline += ["-X", "READY"]
-        assert self.subscriptions, "Missing subscriptions, required for receiver!"
-        self._cmdline.append("-a")
-        self._cmdline.append(",".join(self.subscriptions))
-        if self.receive_count is not None:
-            self._cmdline.append("-c")
-            self._cmdline.append(str(self.receive_count))
-        if self.recv_count is not None:
-            self._cmdline.append("-b")
-            self._cmdline.append(str(self.recv_count))
-        if self.incoming_window is not None:
-            self._cmdline.append("-w")
-            self._cmdline.append(str(self.incoming_window))
-        if self.timeout is not None:
-            self._cmdline.append("-t")
-            self._cmdline.append(str(self.timeout))
-        if self.report_interval is not None:
-            self._cmdline.append("-e")
-            self._cmdline.append(str(self.report_interval))
-        if self.send_reply:
-            self._cmdline.append("-R")
-        if self.outgoing_window is not None:
-            self._cmdline.append("-W")
-            self._cmdline.append(str(self.outgoing_window))
-        if self.forwards:
-            self._cmdline.append("-F")
-            self._cmdline.append(",".join(self.forwards))
-        if self.name is not None:
-            self._cmdline.append("-N")
-            self._cmdline.append(str(self.name))
-
-    def _ready(self):
-        """ wait for subscriptions to complete setup. """
-        r = self._process.stdout.readline()
-        assert r.strip() == "READY", "Unexpected input while waiting for receiver to initialize: %s" % r
-
-class MessengerSenderC(MessengerSender):
-    def __init__(self):
-        MessengerSender.__init__(self)
-        self._command = ["msgr-send"]
-
-def setup_valgrind(self):
-    if "VALGRIND" not in os.environ:
-        raise Skipped("Skipping test - $VALGRIND not set.")
-    super(type(self), self).__init__()
-    self._command = [os.environ["VALGRIND"]] + os.environ["VALGRIND_ARGS"].split(' ') + self._command
-
-class MessengerSenderValgrind(MessengerSenderC):
-    """ Run the C sender under Valgrind
-    """
-    def __init__(self, suppressions=None):
-        setup_valgrind(self)
-
-class MessengerReceiverC(MessengerReceiver):
-    def __init__(self):
-        MessengerReceiver.__init__(self)
-        self._command = ["msgr-recv"]
-
-class MessengerReceiverValgrind(MessengerReceiverC):
-    """ Run the C receiver under Valgrind
-    """
-    def __init__(self, suppressions=None):
-        setup_valgrind(self)
-
-class ReactorSenderC(MessengerSender):
-    def __init__(self):
-        MessengerSender.__init__(self)
-        self._command = ["reactor-send"]
-
-class ReactorSenderValgrind(ReactorSenderC):
-    """ Run the C sender under Valgrind
-    """
-    def __init__(self, suppressions=None):
-        setup_valgrind(self)
-
-class ReactorReceiverC(MessengerReceiver):
-    def __init__(self):
-        MessengerReceiver.__init__(self)
-        self._command = ["reactor-recv"]
-
-class ReactorReceiverValgrind(ReactorReceiverC):
-    """ Run the C receiver under Valgrind
-    """
-    def __init__(self, suppressions=None):
-        setup_valgrind(self)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[05/11] qpid-proton git commit: PROTON-1885: [python] move tests/python to python/tests

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/interop.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/interop.py b/tests/python/proton_tests/interop.py
deleted file mode 100644
index 2825fe4..0000000
--- a/tests/python/proton_tests/interop.py
+++ /dev/null
@@ -1,147 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-from proton import *
-import os
-from . import common
-
-
-def find_test_interop_dir():
-    """Walk up the directory tree to find the tests directory."""
-    f = os.path.dirname(os.path.abspath(__file__))
-    while f and os.path.basename(f) != "tests": f = os.path.dirname(f)
-    f = os.path.join(f, "interop")
-    if not os.path.isdir(f):
-        raise Exception("Cannot find test/interop directory from "+__file__)
-    return f
-
-test_interop_dir=find_test_interop_dir()
-
-class InteropTest(common.Test):
-
-    def setUp(self):
-        self.data = Data()
-        self.message = Message()
-
-    def tearDown(self):
-        self.data = None
-
-    def get_data(self, name):
-        filename = os.path.join(test_interop_dir, name+".amqp")
-        f = open(filename,"rb")
-        try: return f.read()
-        finally: f.close()
-
-    def decode_data(self, encoded):
-        buffer = encoded
-        while buffer:
-            n = self.data.decode(buffer)
-            buffer = buffer[n:]
-        self.data.rewind()
-
-    def decode_data_file(self, name):
-        encoded = self.get_data(name)
-        self.decode_data(encoded)
-        encoded_size = self.data.encoded_size()
-        # Re-encode and verify pre-computed and actual encoded size match.
-        reencoded = self.data.encode()
-        assert encoded_size == len(reencoded), "%d != %d" % (encoded_size, len(reencoded))
-        # verify round trip bytes
-        assert reencoded == encoded, "Value mismatch: %s != %s" % (reencoded, encoded)
-
-    def decode_message_file(self, name):
-        self.message.decode(self.get_data(name))
-        body = self.message.body
-        if str(type(body)) == "<type 'org.apache.qpid.proton.amqp.Binary'>":
-            body = body.array.tostring()
-        self.decode_data(body)
-
-    def assert_next(self, type, value):
-        next_type = self.data.next()
-        assert next_type == type, "Type mismatch: %s != %s"%(
-            Data.type_names[next_type], Data.type_names[type])
-        next_value = self.data.get_object()
-        assert next_value == value, "Value mismatch: %s != %s"%(next_value, value)
-
-    def test_message(self):
-        self.decode_message_file("message")
-        self.assert_next(Data.STRING, "hello")
-        assert self.data.next() is None
-
-    def test_primitives(self):
-        self.decode_data_file("primitives")
-        self.assert_next(Data.BOOL, True)
-        self.assert_next(Data.BOOL, False)
-        self.assert_next(Data.UBYTE, 42)
-        self.assert_next(Data.USHORT, 42)
-        self.assert_next(Data.SHORT, -42)
-        self.assert_next(Data.UINT, 12345)
-        self.assert_next(Data.INT, -12345)
-        self.assert_next(Data.ULONG, 12345)
-        self.assert_next(Data.LONG, -12345)
-        self.assert_next(Data.FLOAT, 0.125)
-        self.assert_next(Data.DOUBLE, 0.125)
-        assert self.data.next() is None
-
-    def test_strings(self):
-        self.decode_data_file("strings")
-        self.assert_next(Data.BINARY, b"abc\0defg")
-        self.assert_next(Data.STRING, "abcdefg")
-        self.assert_next(Data.SYMBOL, "abcdefg")
-        self.assert_next(Data.BINARY, b"")
-        self.assert_next(Data.STRING, "")
-        self.assert_next(Data.SYMBOL, "")
-        assert self.data.next() is None
-
-    def test_described(self):
-        self.decode_data_file("described")
-        self.assert_next(Data.DESCRIBED, Described("foo-descriptor", "foo-value"))
-        self.data.exit()
-
-        assert self.data.next() == Data.DESCRIBED
-        self.data.enter()
-        self.assert_next(Data.INT, 12)
-        self.assert_next(Data.INT, 13)
-        self.data.exit()
-
-        assert self.data.next() is None
-
-    def test_described_array(self):
-        self.decode_data_file("described_array")
-        self.assert_next(Data.ARRAY, Array("int-array", Data.INT, *range(0,10)))
-
-    def test_arrays(self):
-        self.decode_data_file("arrays")
-        self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.INT, *range(0,100)))
-        self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.STRING, *["a", "b", "c"]))
-        self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.INT))
-        assert self.data.next() is None
-
-    def test_lists(self):
-        self.decode_data_file("lists")
-        self.assert_next(Data.LIST, [32, "foo", True])
-        self.assert_next(Data.LIST, [])
-        assert self.data.next() is None
-
-    def test_maps(self):
-        self.decode_data_file("maps")
-        self.assert_next(Data.MAP, {"one":1, "two":2, "three":3 })
-        self.assert_next(Data.MAP, {1:"one", 2:"two", 3:"three"})
-        self.assert_next(Data.MAP, {})
-        assert self.data.next() is None

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/message.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/message.py b/tests/python/proton_tests/message.py
deleted file mode 100644
index 1a2709c..0000000
--- a/tests/python/proton_tests/message.py
+++ /dev/null
@@ -1,275 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-#   http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-import os
-from . import common
-from proton import *
-from uuid import uuid4
-
-class Test(common.Test):
-
-  def setUp(self):
-    self.msg = Message()
-
-  def tearDown(self):
-    self.msg = None
-
-
-class AccessorsTest(Test):
-
-  def _test(self, name, default, values):
-    d = getattr(self.msg, name)
-    assert d == default, (d, default)
-    for v in values:
-      setattr(self.msg, name, v)
-      gotten = getattr(self.msg, name)
-      assert gotten == v, gotten
-
-  def _test_symbol(self, name):
-    self._test(name, symbol(None), (symbol(u"abc.123.#$%"), symbol(u"hello.world")))
-
-  def _test_str(self, name):
-    self._test(name, None, (u"asdf", u"fdsa", u""))
-
-  def _test_time(self, name):
-    self._test(name, 0, (0, 123456789, 987654321))
-
-  def testId(self):
-    self._test("id", None, ("bytes", None, 123, u"string", uuid4()))
-
-  def testCorrelationId(self):
-    self._test("correlation_id", None, ("bytes", None, 123, u"string", uuid4()))
-
-  def testDurable(self):
-    self._test("durable", False, (True, False))
-
-  def testPriority(self):
-    self._test("priority", Message.DEFAULT_PRIORITY, range(0, 255))
-
-  def testTtl(self):
-    self._test("ttl", 0, range(12345, 54321))
-
-  def testFirstAcquirer(self):
-    self._test("first_acquirer", False, (True, False))
-
-  def testDeliveryCount(self):
-    self._test("delivery_count", 0, range(0, 1024))
-
-  def testUserId(self):
-    self._test("user_id", b"", (b"asdf", b"fdsa", b"asd\x00fdsa", b""))
-
-  def testAddress(self):
-    self._test_str("address")
-
-  def testSubject(self):
-    self._test_str("subject")
-
-  def testReplyTo(self):
-    self._test_str("reply_to")
-
-  def testContentType(self):
-    self._test_symbol("content_type")
-
-  def testContentEncoding(self):
-    self._test_symbol("content_encoding")
-
-  def testExpiryTime(self):
-    self._test_time("expiry_time")
-
-  def testCreationTime(self):
-    self._test_time("creation_time")
-
-  def testGroupId(self):
-    self._test_str("group_id")
-
-  def testGroupSequence(self):
-    self._test("group_sequence", 0, (0, -10, 10, 20, -20))
-
-  def testReplyToGroupId(self):
-    self._test_str("reply_to_group_id")
-
-class CodecTest(Test):
-
-  def testProperties(self):
-    self.msg.properties = {}
-    self.msg.properties['key'] = 'value'
-    data = self.msg.encode()
-
-    msg2 = Message()
-    msg2.decode(data)
-
-    assert msg2.properties['key'] == 'value', msg2.properties['key']
-
-  def testRoundTrip(self):
-    self.msg.id = "asdf"
-    self.msg.correlation_id = uuid4()
-    self.msg.ttl = 3
-    self.msg.priority = 100
-    self.msg.address = "address"
-    self.msg.subject = "subject"
-    self.msg.body = 'Hello World!'
-
-    data = self.msg.encode()
-
-    msg2 = Message()
-    msg2.decode(data)
-
-    assert self.msg.id == msg2.id, (self.msg.id, msg2.id)
-    assert self.msg.correlation_id == msg2.correlation_id, (self.msg.correlation_id, msg2.correlation_id)
-    assert self.msg.ttl == msg2.ttl, (self.msg.ttl, msg2.ttl)
-    assert self.msg.priority == msg2.priority, (self.msg.priority, msg2.priority)
-    assert self.msg.address == msg2.address, (self.msg.address, msg2.address)
-    assert self.msg.subject == msg2.subject, (self.msg.subject, msg2.subject)
-    assert self.msg.body == msg2.body, (self.msg.body, msg2.body)
-
-  def testExpiryEncodeAsNull(self):
-    self.msg.group_id = "A" # Force creation and expiry fields to be present
-    data = self.msg.encode()
-
-    decoder = Data()
-
-    # Skip past the headers
-    consumed = decoder.decode(data)
-    decoder.clear()
-    data = data[consumed:]
-
-    decoder.decode(data)
-    dproperties = decoder.get_py_described()
-    # Check we've got the correct described list
-    assert dproperties.descriptor == 0x73, (dproperties.descriptor)
-
-    properties = dproperties.value
-    assert properties[8] == None, properties[8]
-
-  def testCreationEncodeAsNull(self):
-    self.msg.group_id = "A" # Force creation and expiry fields to be present
-    data = self.msg.encode()
-
-    decoder = Data()
-
-    # Skip past the headers
-    consumed = decoder.decode(data)
-    decoder.clear()
-    data = data[consumed:]
-
-    decoder.decode(data)
-    dproperties = decoder.get_py_described()
-    # Check we've got the correct described list
-    assert dproperties.descriptor == 0x73, (dproperties.descriptor)
-
-    properties = dproperties.value
-    assert properties[9] == None, properties[9]
-
-  def testGroupSequenceEncodeAsNull(self):
-    self.msg.reply_to_group_id = "R" # Force group_id and group_sequence fields to be present
-    data = self.msg.encode()
-
-    decoder = Data()
-
-    # Skip past the headers
-    consumed = decoder.decode(data)
-    decoder.clear()
-    data = data[consumed:]
-
-    decoder.decode(data)
-    dproperties = decoder.get_py_described()
-    # Check we've got the correct described list
-    assert dproperties.descriptor == 0x73, (dproperties.descriptor)
-
-    properties = dproperties.value
-    assert properties[10] == None, properties[10]
-    assert properties[11] == None, properties[11]
-
-  def testGroupSequenceEncodeAsNonNull(self):
-    self.msg.group_id = "G"
-    self.msg.reply_to_group_id = "R" # Force group_id and group_sequence fields to be present
-    data = self.msg.encode()
-
-    decoder = Data()
-
-    # Skip past the headers
-    consumed = decoder.decode(data)
-    decoder.clear()
-    data = data[consumed:]
-
-    decoder.decode(data)
-    dproperties = decoder.get_py_described()
-    # Check we've got the correct described list
-    assert dproperties.descriptor == 0x73, (dproperties.descriptor)
-
-    properties = dproperties.value
-    assert properties[10] == 'G', properties[10]
-    assert properties[11] == 0, properties[11]
-
-  def testDefaultCreationExpiryDecode(self):
-    # This is a message with everything filled explicitly as null or zero in LIST32 HEADER and PROPERTIES lists
-    data = b'\x00\x53\x70\xd0\x00\x00\x00\x0a\x00\x00\x00\x05\x42\x40\x40\x42\x52\x00\x00\x53\x73\xd0\x00\x00\x00\x12\x00\x00\x00\x0d\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x52\x00\x40'
-    msg2 = Message()
-    msg2.decode(data)
-    assert msg2.expiry_time == 0, (msg2.expiry_time)
-    assert msg2.creation_time == 0, (msg2.creation_time)
-
-    # The same message with LIST8s instead
-    data = b'\x00\x53\x70\xc0\x07\x05\x42\x40\x40\x42\x52\x00\x00\x53\x73\xc0\x0f\x0d\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x52\x00\x40'
-    msg3 = Message()
-    msg3.decode(data)
-    assert msg2.expiry_time == 0, (msg2.expiry_time)
-    assert msg2.creation_time == 0, (msg2.creation_time)
-
-    # Minified message with zero length HEADER and PROPERTIES lists
-    data = b'\x00\x53\x70\x45' b'\x00\x53\x73\x45'
-    msg4 = Message()
-    msg4.decode(data)
-    assert msg2.expiry_time == 0, (msg2.expiry_time)
-    assert msg2.creation_time == 0, (msg2.creation_time)
-
-  def testDefaultPriorityEncode(self):
-    assert self.msg.priority == 4, (self.msg.priority)
-    self.msg.ttl = 0.003 # field after priority, so forces priority to be present
-    data = self.msg.encode()
-
-    decoder = Data()
-    decoder.decode(data)
-
-    dheaders = decoder.get_py_described()
-    # Check we've got the correct described list
-    assert dheaders.descriptor == 0x70, (dheaders.descriptor)
-
-    # Check that the priority field (second field) is encoded as null
-    headers = dheaders.value
-    assert headers[1] == None, (headers[1])
-
-  def testDefaultPriorityDecode(self):
-    # This is a message with everything filled explicitly as null or zero in LIST32 HEADER and PROPERTIES lists
-    data = b'\x00\x53\x70\xd0\x00\x00\x00\x0a\x00\x00\x00\x05\x42\x40\x40\x42\x52\x00\x00\x53\x73\xd0\x00\x00\x00\x22\x00\x00\x00\x0d\x40\x40\x40\x40\x40\x40\x40\x40\x83\x00\x00\x00\x00\x00\x00\x00\x00\x83\x00\x00\x00\x00\x00\x00\x00\x00\x40\x52\x00\x40'
-    msg2 = Message()
-    msg2.decode(data)
-    assert msg2.priority == 4, (msg2.priority)
-
-    # The same message with LIST8s instead
-    data = b'\x00\x53\x70\xc0\x07\x05\x42\x40\x40\x42\x52\x00\x00\x53\x73\xc0\x1f\x0d\x40\x40\x40\x40\x40\x40\x40\x40\x83\x00\x00\x00\x00\x00\x00\x00\x00\x83\x00\x00\x00\x00\x00\x00\x00\x00\x40\x52\x00\x40'
-    msg3 = Message()
-    msg3.decode(data)
-    assert msg3.priority == 4, (msg3.priority)
-
-    # Minified message with zero length HEADER and PROPERTIES lists
-    data = b'\x00\x53\x70\x45' b'\x00\x53\x73\x45'
-    msg4 = Message()
-    msg4.decode(data)
-    assert msg4.priority == 4, (msg4.priority)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/reactor.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/reactor.py b/tests/python/proton_tests/reactor.py
deleted file mode 100644
index 1b1e2fc..0000000
--- a/tests/python/proton_tests/reactor.py
+++ /dev/null
@@ -1,485 +0,0 @@
-from __future__ import absolute_import
-#
-# 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.
-#
-
-import time
-import sys
-from .common import Test, SkipTest, TestServer, free_tcp_port, ensureCanTestExtendedSASL
-from proton.reactor import Container, Reactor, ApplicationEvent, EventInjector
-from proton.handlers import Handshaker, MessagingHandler
-from proton import Handler, Url
-
-class Barf(Exception):
-    pass
-
-class BarfOnInit:
-
-    def on_reactor_init(self, event):
-        raise Barf()
-
-    def on_connection_init(self, event):
-        raise Barf()
-
-    def on_session_init(self, event):
-        raise Barf()
-
-    def on_link_init(self, event):
-        raise Barf()
-
-class BarfOnTask:
-
-    def on_timer_task(self, event):
-        raise Barf()
-
-class BarfOnFinal:
-    init = False
-
-    def on_reactor_init(self, event):
-        self.init = True
-
-    def on_reactor_final(self, event):
-        raise Barf()
-    
-class BarfOnFinalDerived(Handshaker):
-    init = False
-    
-    def on_reactor_init(self, event):
-        self.init = True
-
-    def on_reactor_final(self, event):
-        raise Barf()
-    
-class ExceptionTest(Test):
-
-    def setUp(self):
-        self.reactor = Reactor()
-
-    def test_reactor_final(self):
-        self.reactor.global_handler = BarfOnFinal()
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_global_set(self):
-        self.reactor.global_handler = BarfOnInit()
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_global_add(self):
-        self.reactor.global_handler.add(BarfOnInit())
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_reactor_set(self):
-        self.reactor.handler = BarfOnInit()
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_reactor_add(self):
-        self.reactor.handler.add(BarfOnInit())
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_connection(self):
-        self.reactor.connection(BarfOnInit())
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_connection_set(self):
-        c = self.reactor.connection()
-        c.handler = BarfOnInit()
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_connection_add(self):
-        c = self.reactor.connection()
-        c.handler = object()
-        c.handler.add(BarfOnInit())
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_session_set(self):
-        c = self.reactor.connection()
-        s = c.session()
-        s.handler = BarfOnInit()
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_session_add(self):
-        c = self.reactor.connection()
-        s = c.session()
-        s.handler = object()
-        s.handler.add(BarfOnInit())
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_link_set(self):
-        c = self.reactor.connection()
-        s = c.session()
-        l = s.sender("xxx")
-        l.handler = BarfOnInit()
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_link_add(self):
-        c = self.reactor.connection()
-        s = c.session()
-        l = s.sender("xxx")
-        l.handler = object()
-        l.handler.add(BarfOnInit())
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_schedule(self):
-        self.reactor.schedule(0, BarfOnTask())
-        try:
-            self.reactor.run()
-            assert False, "expected to barf"
-        except Barf:
-            pass
-
-    def test_schedule_many_nothings(self):
-        class Nothing:
-            results = []
-            def on_timer_task(self, event):
-                self.results.append(None)
-        num = 12345
-        for a in range(num):
-            self.reactor.schedule(0, Nothing())
-        self.reactor.run()
-        assert len(Nothing.results) == num
-
-    def test_schedule_many_nothing_refs(self):
-        class Nothing:
-            results = []
-            def on_timer_task(self, event):
-                self.results.append(None)
-        num = 12345
-        tasks = []
-        for a in range(num):
-            tasks.append(self.reactor.schedule(0, Nothing()))
-        self.reactor.run()
-        assert len(Nothing.results) == num
-
-    def test_schedule_many_nothing_refs_cancel_before_run(self):
-        class Nothing:
-            results = []
-            def on_timer_task(self, event):
-                self.results.append(None)
-        num = 12345
-        tasks = []
-        for a in range(num):
-            tasks.append(self.reactor.schedule(0, Nothing()))
-        for task in tasks:
-            task.cancel()
-        self.reactor.run()
-        assert len(Nothing.results) == 0
-
-    def test_schedule_cancel(self):
-        barf = self.reactor.schedule(10, BarfOnTask())
-        class CancelBarf:
-            def __init__(self, barf):
-                self.barf = barf
-            def on_timer_task(self, event):
-                self.barf.cancel()
-                pass
-        self.reactor.schedule(0, CancelBarf(barf))
-        now = self.reactor.mark()
-        try:
-            self.reactor.run()
-            elapsed = self.reactor.mark() - now
-            assert elapsed < 10, "expected cancelled task to not delay the reactor by %s" % elapsed
-        except Barf:
-            assert False, "expected barf to be cancelled"
-
-    def test_schedule_cancel_many(self):
-        num = 12345
-        barfs = set()
-        for a in range(num):
-            barf = self.reactor.schedule(10*(a+1), BarfOnTask())
-            class CancelBarf:
-                def __init__(self, barf):
-                    self.barf = barf
-                def on_timer_task(self, event):
-                    self.barf.cancel()
-                    barfs.discard(self.barf)
-                    pass
-            self.reactor.schedule(0, CancelBarf(barf))
-            barfs.add(barf)
-        now = self.reactor.mark()
-        try:
-            self.reactor.run()
-            elapsed = self.reactor.mark() - now
-            assert elapsed < num, "expected cancelled task to not delay the reactor by %s" % elapsed
-            assert not barfs, "expected all barfs to be discarded"
-        except Barf:
-            assert False, "expected barf to be cancelled"
-
-
-class ApplicationEventTest(Test):
-    """Test application defined events and handlers."""
-
-    class MyTestServer(TestServer):
-        def __init__(self):
-            super(ApplicationEventTest.MyTestServer, self).__init__()
-
-    class MyHandler(Handler):
-        def __init__(self, test):
-            super(ApplicationEventTest.MyHandler, self).__init__()
-            self._test = test
-
-        def on_hello(self, event):
-            # verify PROTON-1056
-            self._test.hello_rcvd = str(event)
-
-        def on_goodbye(self, event):
-            self._test.goodbye_rcvd = str(event)
-
-    def setUp(self):
-        import os
-        if not hasattr(os, 'pipe'):
-          # KAG: seems like Jython doesn't have an os.pipe() method
-          raise SkipTest()
-        if os.name=="nt":
-          # Correct implementation on Windows is complicated
-          raise SkipTest("PROTON-1071")
-        self.server = ApplicationEventTest.MyTestServer()
-        self.server.reactor.handler.add(ApplicationEventTest.MyHandler(self))
-        self.event_injector = EventInjector()
-        self.hello_event = ApplicationEvent("hello")
-        self.goodbye_event = ApplicationEvent("goodbye")
-        self.server.reactor.selectable(self.event_injector)
-        self.hello_rcvd = None
-        self.goodbye_rcvd = None
-        self.server.start()
-
-    def tearDown(self):
-        self.server.stop()
-
-    def _wait_for(self, predicate, timeout=10.0):
-        deadline = time.time() + timeout
-        while time.time() < deadline:
-            if predicate():
-                break
-            time.sleep(0.1)
-        assert predicate()
-
-    def test_application_events(self):
-        self.event_injector.trigger(self.hello_event)
-        self._wait_for(lambda: self.hello_rcvd is not None)
-        self.event_injector.trigger(self.goodbye_event)
-        self._wait_for(lambda: self.goodbye_rcvd is not None)
-
-
-class AuthenticationTestHandler(MessagingHandler):
-    def __init__(self):
-        super(AuthenticationTestHandler, self).__init__()
-        port = free_tcp_port()
-        self.url = "localhost:%i" % port
-        self.verified = False
-
-    def on_start(self, event):
-        self.listener = event.container.listen(self.url)
-
-    def on_connection_opened(self, event):
-        event.connection.close()
-
-    def on_connection_opening(self, event):
-        assert event.connection.transport.user == "user@proton"
-        self.verified = True
-
-    def on_connection_closed(self, event):
-        event.connection.close()
-        self.listener.close()
-
-    def on_connection_error(self, event):
-        event.connection.close()
-        self.listener.close()
-
-class ContainerTest(Test):
-    """Test container subclass of reactor."""
-
-    def test_event_has_container_attribute(self):
-        ensureCanTestExtendedSASL()
-        class TestHandler(MessagingHandler):
-            def __init__(self):
-                super(TestHandler, self).__init__()
-                port = free_tcp_port()
-                self.url = "localhost:%i" % port
-
-            def on_start(self, event):
-                self.listener = event.container.listen(self.url)
-
-            def on_connection_closing(self, event):
-                event.connection.close()
-                self.listener.close()
-        test_handler = TestHandler()
-        container = Container(test_handler)
-        class ConnectionHandler(MessagingHandler):
-            def __init__(self):
-                super(ConnectionHandler, self).__init__()
-
-            def on_connection_opened(self, event):
-                event.connection.close()
-                assert event.container == event.reactor
-                assert event.container == container
-        container.connect(test_handler.url, handler=ConnectionHandler())
-        container.run()
-
-    def test_authentication_via_url(self):
-        ensureCanTestExtendedSASL()
-        test_handler = AuthenticationTestHandler()
-        container = Container(test_handler)
-        container.connect("%s:password@%s" % ("user%40proton", test_handler.url), reconnect=False)
-        container.run()
-        assert test_handler.verified
-
-    def test_authentication_via_container_attributes(self):
-        ensureCanTestExtendedSASL()
-        test_handler = AuthenticationTestHandler()
-        container = Container(test_handler)
-        container.user = "user@proton"
-        container.password = "password"
-        container.connect(test_handler.url, reconnect=False)
-        container.run()
-        assert test_handler.verified
-
-    def test_authentication_via_kwargs(self):
-        ensureCanTestExtendedSASL()
-        test_handler = AuthenticationTestHandler()
-        container = Container(test_handler)
-        container.connect(test_handler.url, user="user@proton", password="password", reconnect=False)
-        container.run()
-        assert test_handler.verified
-
-    class _ServerHandler(MessagingHandler):
-        def __init__(self, host):
-            super(ContainerTest._ServerHandler, self).__init__()
-            self.host = host
-            port = free_tcp_port()
-            self.port = free_tcp_port()
-            self.client_addr = None
-            self.peer_hostname = None
-
-        def on_start(self, event):
-            self.listener = event.container.listen("%s:%s" % (self.host, self.port))
-
-        def on_connection_opened(self, event):
-            self.client_addr = event.reactor.get_connection_address(event.connection)
-            self.peer_hostname = event.connection.remote_hostname
-
-        def on_connection_closing(self, event):
-            event.connection.close()
-            self.listener.close()
-
-    class _ClientHandler(MessagingHandler):
-        def __init__(self):
-            super(ContainerTest._ClientHandler, self).__init__()
-            self.server_addr = None
-
-        def on_connection_opened(self, event):
-            self.server_addr = event.reactor.get_connection_address(event.connection)
-            event.connection.close()
-
-    def test_numeric_hostname(self):
-        ensureCanTestExtendedSASL()
-        server_handler = ContainerTest._ServerHandler("127.0.0.1")
-        client_handler = ContainerTest._ClientHandler()
-        container = Container(server_handler)
-        container.connect(url=Url(host="127.0.0.1",
-                                  port=server_handler.port),
-                          handler=client_handler)
-        container.run()
-        assert server_handler.client_addr
-        assert client_handler.server_addr
-        assert server_handler.peer_hostname == "127.0.0.1", server_handler.peer_hostname
-        assert client_handler.server_addr.rsplit(':', 1)[1] == str(server_handler.port)
-
-    def test_non_numeric_hostname(self):
-        ensureCanTestExtendedSASL()
-        server_handler = ContainerTest._ServerHandler("localhost")
-        client_handler = ContainerTest._ClientHandler()
-        container = Container(server_handler)
-        container.connect(url=Url(host="localhost",
-                                  port=server_handler.port),
-                          handler=client_handler)
-        container.run()
-        assert server_handler.client_addr
-        assert client_handler.server_addr
-        assert server_handler.peer_hostname == "localhost", server_handler.peer_hostname
-        assert client_handler.server_addr.rsplit(':', 1)[1] == str(server_handler.port)
-
-    def test_virtual_host(self):
-        ensureCanTestExtendedSASL()
-        server_handler = ContainerTest._ServerHandler("localhost")
-        container = Container(server_handler)
-        conn = container.connect(url=Url(host="localhost",
-                                         port=server_handler.port),
-                                 handler=ContainerTest._ClientHandler(),
-                                 virtual_host="a.b.c.org")
-        container.run()
-        assert server_handler.peer_hostname == "a.b.c.org", server_handler.peer_hostname
-
-    def test_no_virtual_host(self):
-        # explicitly setting an empty virtual host should prevent the hostname
-        # field from being sent in the Open performative when using the
-        # Python Container.
-        server_handler = ContainerTest._ServerHandler("localhost")
-        container = Container(server_handler)
-        conn = container.connect(url=Url(host="localhost",
-                                         port=server_handler.port),
-                                 handler=ContainerTest._ClientHandler(),
-                                 virtual_host="")
-        container.run()
-        assert server_handler.peer_hostname is None, server_handler.peer_hostname

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/sasl.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/sasl.py b/tests/python/proton_tests/sasl.py
deleted file mode 100644
index 68ae200..0000000
--- a/tests/python/proton_tests/sasl.py
+++ /dev/null
@@ -1,587 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-#   http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-from __future__ import absolute_import
-
-import sys, os
-from . import common
-from . import engine
-
-from proton import *
-from .common import pump, Skipped
-
-def _sslCertpath(file):
-    """ Return the full path to the certificate, keyfile, etc.
-    """
-    if os.name=="nt":
-        if file.find("private-key")!=-1:
-            # The private key is not in a separate store
-            return None
-        # Substitute pkcs#12 equivalent for the CA/key store
-        if file.endswith(".pem"):
-            file = file[:-4] + ".p12"
-    return os.path.join(os.path.dirname(__file__),
-                        "ssl_db/%s" % file)
-
-def _testSaslMech(self, mech, clientUser='user@proton', authUser='user@proton', encrypted=False, authenticated=True):
-  self.s1.allowed_mechs(mech)
-  self.c1.open()
-  self.c2.open()
-
-  pump(self.t1, self.t2, 1024)
-
-  if encrypted is not None:
-    assert self.t2.encrypted == encrypted, encrypted
-    assert self.t1.encrypted == encrypted, encrypted
-
-  assert self.t2.authenticated == authenticated, authenticated
-  assert self.t1.authenticated == authenticated, authenticated
-  if authenticated:
-    # Server
-    assert self.t2.user == authUser
-    assert self.s2.user == authUser
-    assert self.s2.mech == mech.strip()
-    assert self.s2.outcome == SASL.OK, self.s2.outcome
-    assert self.c2.state & Endpoint.LOCAL_ACTIVE and self.c2.state & Endpoint.REMOTE_ACTIVE,\
-      "local_active=%s, remote_active=%s" % (self.c1.state & Endpoint.LOCAL_ACTIVE, self.c1.state & Endpoint.REMOTE_ACTIVE)
-    # Client
-    assert self.t1.user == clientUser
-    assert self.s1.user == clientUser
-    assert self.s1.mech == mech.strip()
-    assert self.s1.outcome == SASL.OK, self.s1.outcome
-    assert self.c1.state & Endpoint.LOCAL_ACTIVE and self.c1.state & Endpoint.REMOTE_ACTIVE,\
-      "local_active=%s, remote_active=%s" % (self.c1.state & Endpoint.LOCAL_ACTIVE, self.c1.state & Endpoint.REMOTE_ACTIVE)
-  else:
-    # Server
-    assert self.t2.user == None
-    assert self.s2.user == None
-    assert self.s2.outcome != SASL.OK, self.s2.outcome
-    # Client
-    assert self.t1.user == clientUser
-    assert self.s1.user == clientUser
-    assert self.s1.outcome != SASL.OK, self.s1.outcome
-
-class Test(common.Test):
-  pass
-
-def consumeAllOuput(t):
-  stops = 0
-  while stops<1:
-    out = t.peek(1024)
-    l = len(out) if out else 0
-    t.pop(l)
-    if l <= 0:
-      stops += 1
-
-class SaslTest(Test):
-
-  def setUp(self):
-    self.t1 = Transport()
-    self.s1 = SASL(self.t1)
-    self.t2 = Transport(Transport.SERVER)
-    self.t2.max_frame_size = 65536
-    self.s2 = SASL(self.t2)
-
-  def pump(self):
-    pump(self.t1, self.t2, 1024)
-
-  # We have to generate the client frames manually because proton does not
-  # generate pipelined SASL and AMQP frames together
-  def testIllegalProtocolLayering(self):
-    # Server
-    self.s2.allowed_mechs('ANONYMOUS')
-
-    c2 = Connection()
-    self.t2.bind(c2)
-
-    assert self.s2.outcome is None
-
-    # Push client bytes into server
-    self.t2.push(
-        # SASL
-        b'AMQP\x03\x01\x00\x00'
-        # @sasl-init(65) [mechanism=:ANONYMOUS, initial-response=b"anonymous@fuschia"]
-        b'\x00\x00\x002\x02\x01\x00\x00\x00SA\xd0\x00\x00\x00"\x00\x00\x00\x02\xa3\x09ANONYMOUS\xa0\x11anonymous@fuschia'
-        # SASL (again illegally)
-        b'AMQP\x03\x01\x00\x00'
-        # @sasl-init(65) [mechanism=:ANONYMOUS, initial-response=b"anonymous@fuschia"]
-        b'\x00\x00\x002\x02\x01\x00\x00\x00SA\xd0\x00\x00\x00"\x00\x00\x00\x02\xa3\x09ANONYMOUS\xa0\x11anonymous@fuschia'
-        # AMQP
-        b'AMQP\x00\x01\x00\x00'
-        # @open(16) [container-id="", channel-max=1234]
-        b'\x00\x00\x00!\x02\x00\x00\x00\x00S\x10\xd0\x00\x00\x00\x11\x00\x00\x00\x0a\xa1\x00@@`\x04\xd2@@@@@@'
-        )
-
-    consumeAllOuput(self.t2)
-
-    assert self.t2.condition
-    assert self.t2.closed
-    assert not c2.state & Endpoint.REMOTE_ACTIVE
-
-  def testPipelinedClient(self):
-    # Server
-    self.s2.allowed_mechs('ANONYMOUS')
-
-    c2 = Connection()
-    self.t2.bind(c2)
-
-    assert self.s2.outcome is None
-
-    # Push client bytes into server
-    self.t2.push(
-        # SASL
-        b'AMQP\x03\x01\x00\x00'
-        # @sasl-init(65) [mechanism=:ANONYMOUS, initial-response=b"anonymous@fuschia"]
-        b'\x00\x00\x002\x02\x01\x00\x00\x00SA\xd0\x00\x00\x00"\x00\x00\x00\x02\xa3\x09ANONYMOUS\xa0\x11anonymous@fuschia'
-        # AMQP
-        b'AMQP\x00\x01\x00\x00'
-        # @open(16) [container-id="", channel-max=1234]
-        b'\x00\x00\x00!\x02\x00\x00\x00\x00S\x10\xd0\x00\x00\x00\x11\x00\x00\x00\x0a\xa1\x00@@`\x04\xd2@@@@@@'
-        )
-
-    consumeAllOuput(self.t2)
-
-    assert not self.t2.condition
-    assert self.s2.outcome == SASL.OK
-    assert c2.state & Endpoint.REMOTE_ACTIVE
-
-  def testPipelinedServer(self):
-    # Client
-    self.s1.allowed_mechs('ANONYMOUS')
-
-    c1 = Connection()
-    self.t1.bind(c1)
-
-    assert self.s1.outcome is None
-
-    # Push server bytes into client
-    # Commented out lines in this test are where the client input processing doesn't
-    # run after output processing even though there is input waiting
-    self.t1.push(
-        # SASL
-        b'AMQP\x03\x01\x00\x00'
-        # @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:ANONYMOUS]]
-        b'\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS'
-        # @sasl-outcome(68) [code=0]
-        b'\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00'
-        # AMQP
-        b'AMQP\x00\x01\x00\x00'
-        # @open(16) [container-id="", channel-max=1234]
-        b'\x00\x00\x00!\x02\x00\x00\x00\x00S\x10\xd0\x00\x00\x00\x11\x00\x00\x00\x0a\xa1\x00@@`\x04\xd2@@@@@@'
-        )
-
-    consumeAllOuput(self.t1)
-
-    assert self.s1.outcome == SASL.OK
-    assert c1.state & Endpoint.REMOTE_ACTIVE
-
-  def testPipelined2(self):
-    out1 = self.t1.peek(1024)
-    self.t1.pop(len(out1))
-    self.t2.push(out1)
-
-    self.s2.allowed_mechs('ANONYMOUS')
-    c2 = Connection()
-    c2.open()
-    self.t2.bind(c2)
-
-    out2 = self.t2.peek(1024)
-    self.t2.pop(len(out2))
-    self.t1.push(out2)
-
-    out1 = self.t1.peek(1024)
-    assert len(out1) > 0
-
-  def testFracturedSASL(self):
-    """ PROTON-235
-    """
-    assert self.s1.outcome is None
-
-    # self.t1.trace(Transport.TRACE_FRM)
-
-    out = self.t1.peek(1024)
-    self.t1.pop(len(out))
-    self.t1.push(b"AMQP\x03\x01\x00\x00")
-    out = self.t1.peek(1024)
-    self.t1.pop(len(out))
-    self.t1.push(b"\x00\x00\x00")
-    out = self.t1.peek(1024)
-    self.t1.pop(len(out))
-
-    self.t1.push(b"6\x02\x01\x00\x00\x00S@\xc0\x29\x01\xe0\x26\x04\xa3\x05PLAIN\x0aDIGEST-MD5\x09ANONYMOUS\x08CRAM-MD5")
-    out = self.t1.peek(1024)
-    self.t1.pop(len(out))
-    self.t1.push(b"\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00")
-    out = self.t1.peek(1024)
-    self.t1.pop(len(out))
-    while out:
-      out = self.t1.peek(1024)
-      self.t1.pop(len(out))
-
-    assert self.s1.outcome == SASL.OK, self.s1.outcome
-
-  def test_singleton(self):
-      """Verify that only a single instance of SASL can exist per Transport"""
-      transport = Transport()
-      attr = object()
-      sasl1 = SASL(transport)
-      sasl1.my_attribute = attr
-      sasl2 = transport.sasl()
-      sasl3 = SASL(transport)
-      assert sasl1 == sasl2
-      assert sasl1 == sasl3
-      assert sasl1.my_attribute == attr
-      assert sasl2.my_attribute == attr
-      assert sasl3.my_attribute == attr
-      transport = Transport()
-      sasl1 = transport.sasl()
-      sasl1.my_attribute = attr
-      sasl2 = SASL(transport)
-      assert sasl1 == sasl2
-      assert sasl1.my_attribute == attr
-      assert sasl2.my_attribute == attr
-
-  def testSaslSkipped(self):
-    """Verify that the server (with SASL) correctly handles a client without SASL"""
-    self.t1 = Transport()
-    self.t2.require_auth(False)
-    self.pump()
-    assert self.s2.outcome == None
-    assert self.t2.condition == None
-    assert self.t2.authenticated == False
-    assert self.s1.outcome == None
-    assert self.t1.condition == None
-    assert self.t1.authenticated == False
-
-  def testSaslSkippedFail(self):
-    """Verify that the server (with SASL) correctly handles a client without SASL"""
-    self.t1 = Transport()
-    self.t2.require_auth(True)
-    self.pump()
-    assert self.s2.outcome == None
-    assert self.t2.condition != None
-    assert self.s1.outcome == None
-    assert self.t1.condition != None
-
-  def testMechNotFound(self):
-    self.c1 = Connection()
-    self.c1.open()
-    self.t1.bind(self.c1)
-    self.s1.allowed_mechs('IMPOSSIBLE')
-
-    self.pump()
-
-    assert self.t2.authenticated == False
-    assert self.t1.authenticated == False
-    assert self.s1.outcome != SASL.OK
-    assert self.s2.outcome != SASL.OK
-
-class SASLMechTest(Test):
-  def setUp(self):
-    self.t1 = Transport()
-    self.s1 = SASL(self.t1)
-    self.t2 = Transport(Transport.SERVER)
-    self.s2 = SASL(self.t2)
-
-    self.c1 = Connection()
-    self.c1.user = 'user@proton'
-    self.c1.password = 'password'
-    self.c1.hostname = 'localhost'
-
-    self.c2 = Connection()
-
-  def testANON(self):
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'ANONYMOUS', authUser='anonymous')
-
-  def testCRAMMD5(self):
-    common.ensureCanTestExtendedSASL()
-
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'CRAM-MD5')
-
-  def testDIGESTMD5(self):
-    common.ensureCanTestExtendedSASL()
-
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'DIGEST-MD5')
-
-  # PLAIN shouldn't work without encryption without special setting
-  def testPLAINfail(self):
-    common.ensureCanTestExtendedSASL()
-
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'PLAIN', authenticated=False)
-
-  # Client won't accept PLAIN even if offered by server without special setting
-  def testPLAINClientFail(self):
-    common.ensureCanTestExtendedSASL()
-
-    self.s2.allow_insecure_mechs = True
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'PLAIN', authenticated=False)
-
-  # PLAIN will only work if both ends are specially set up
-  def testPLAIN(self):
-    common.ensureCanTestExtendedSASL()
-
-    self.s1.allow_insecure_mechs = True
-    self.s2.allow_insecure_mechs = True
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'PLAIN')
-
-# SCRAM not supported before Cyrus SASL 2.1.26
-# so not universal and hence need a test for support
-# to keep it in tests.
-#  def testSCRAMSHA1(self):
-#    common.ensureCanTestExtendedSASL()
-#
-#    self.t1.bind(self.c1)
-#    self.t2.bind(self.c2)
-#    _testSaslMech(self, 'SCRAM-SHA-1')
-
-def _sslConnection(domain, transport, connection):
-  transport.bind(connection)
-  ssl = SSL(transport, domain, None )
-  return connection
-
-class SSLSASLTest(Test):
-  def setUp(self):
-    if not common.isSSLPresent():
-      raise Skipped("No SSL libraries found.")
-
-    self.server_domain = SSLDomain(SSLDomain.MODE_SERVER)
-    self.client_domain = SSLDomain(SSLDomain.MODE_CLIENT)
-
-    self.t1 = Transport()
-    self.s1 = SASL(self.t1)
-    self.t2 = Transport(Transport.SERVER)
-    self.s2 = SASL(self.t2)
-
-    self.c1 = Connection()
-    self.c2 = Connection()
-
-  def testSSLPlainSimple(self):
-    if not SASL.extended():
-      raise Skipped("Simple SASL server does not support PLAIN")
-    common.ensureCanTestExtendedSASL()
-
-    clientUser = 'user@proton'
-    mech = 'PLAIN'
-
-    self.c1.user = clientUser
-    self.c1.password = 'password'
-    self.c1.hostname = 'localhost'
-
-    ssl1 = _sslConnection(self.client_domain, self.t1, self.c1)
-    ssl2 = _sslConnection(self.server_domain, self.t2, self.c2)
-
-    _testSaslMech(self, mech, encrypted=True)
-
-  def testSSLPlainSimpleFail(self):
-    if not SASL.extended():
-      raise Skipped("Simple SASL server does not support PLAIN")
-    common.ensureCanTestExtendedSASL()
-
-    clientUser = 'usr@proton'
-    mech = 'PLAIN'
-
-    self.c1.user = clientUser
-    self.c1.password = 'password'
-    self.c1.hostname = 'localhost'
-
-    ssl1 = _sslConnection(self.client_domain, self.t1, self.c1)
-    ssl2 = _sslConnection(self.server_domain, self.t2, self.c2)
-
-    _testSaslMech(self, mech, clientUser='usr@proton', encrypted=True, authenticated=False)
-
-  def testSSLExternalSimple(self):
-    if os.name=="nt":
-      extUser = 'O=Client, CN=127.0.0.1'
-    else:
-      extUser = 'O=Client,CN=127.0.0.1'
-    mech = 'EXTERNAL'
-
-    self.server_domain.set_credentials(_sslCertpath("server-certificate.pem"),
-                                       _sslCertpath("server-private-key.pem"),
-                                       "server-password")
-    self.server_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem"))
-    self.server_domain.set_peer_authentication(SSLDomain.VERIFY_PEER,
-                                               _sslCertpath("ca-certificate.pem") )
-    self.client_domain.set_credentials(_sslCertpath("client-certificate.pem"),
-                                       _sslCertpath("client-private-key.pem"),
-                                       "client-password")
-    self.client_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem"))
-    self.client_domain.set_peer_authentication(SSLDomain.VERIFY_PEER)
-
-    ssl1 = _sslConnection(self.client_domain, self.t1, self.c1)
-    ssl2 = _sslConnection(self.server_domain, self.t2, self.c2)
-
-    _testSaslMech(self, mech, clientUser=None, authUser=extUser, encrypted=True)
-
-  def testSSLExternalSimpleFail(self):
-    mech = 'EXTERNAL'
-
-    self.server_domain.set_credentials(_sslCertpath("server-certificate.pem"),
-                                       _sslCertpath("server-private-key.pem"),
-                                       "server-password")
-    self.server_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem"))
-    self.server_domain.set_peer_authentication(SSLDomain.VERIFY_PEER,
-                                               _sslCertpath("ca-certificate.pem") )
-    self.client_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem"))
-    self.client_domain.set_peer_authentication(SSLDomain.VERIFY_PEER)
-
-    ssl1 = _sslConnection(self.client_domain, self.t1, self.c1)
-    ssl2 = _sslConnection(self.server_domain, self.t2, self.c2)
-
-    _testSaslMech(self, mech, clientUser=None, authUser=None, encrypted=None, authenticated=False)
-
-class SASLEventTest(engine.CollectorTest):
-  def setUp(self):
-    engine.CollectorTest.setUp(self)
-    self.t1 = Transport()
-    self.s1 = SASL(self.t1)
-    self.t2 = Transport(Transport.SERVER)
-    self.s2 = SASL(self.t2)
-
-    self.c1 = Connection()
-    self.c1.user = 'user@proton'
-    self.c1.password = 'password'
-    self.c1.hostname = 'localhost'
-
-    self.c2 = Connection()
-
-    self.collector = Collector()
-
-  def testNormalAuthenticationClient(self):
-    common.ensureCanTestExtendedSASL()
-    self.c1.collect(self.collector)
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'DIGEST-MD5')
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.CONNECTION_REMOTE_OPEN)
-
-  def testNormalAuthenticationServer(self):
-    common.ensureCanTestExtendedSASL()
-    self.c2.collect(self.collector)
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'DIGEST-MD5')
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.CONNECTION_REMOTE_OPEN)
-
-  def testFailedAuthenticationClient(self):
-    common.ensureCanTestExtendedSASL()
-    clientUser = "usr@proton"
-    self.c1.user = clientUser
-    self.c1.collect(self.collector)
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'DIGEST-MD5', clientUser=clientUser, authenticated=False)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.TRANSPORT_ERROR,
-                Event.TRANSPORT_TAIL_CLOSED,
-                Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testFailedAuthenticationServer(self):
-    common.ensureCanTestExtendedSASL()
-    clientUser = "usr@proton"
-    self.c1.user = clientUser
-    self.c2.collect(self.collector)
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'DIGEST-MD5', clientUser=clientUser, authenticated=False)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.TRANSPORT_ERROR,
-                Event.TRANSPORT_TAIL_CLOSED,
-                Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testNoMechClient(self):
-    common.ensureCanTestExtendedSASL()
-    self.c1.collect(self.collector)
-    self.s2.allowed_mechs('IMPOSSIBLE')
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'DIGEST-MD5', authenticated=False)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.TRANSPORT_ERROR,
-                Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testNoMechServer(self):
-    common.ensureCanTestExtendedSASL()
-    self.c2.collect(self.collector)
-    self.s2.allowed_mechs('IMPOSSIBLE')
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'DIGEST-MD5', authenticated=False)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.TRANSPORT_TAIL_CLOSED,
-                Event.TRANSPORT_ERROR, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testDisallowedMechClient(self):
-    self.c1.collect(self.collector)
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'IMPOSSIBLE', authenticated=False)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.TRANSPORT_ERROR,
-                Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testDisallowedMechServer(self):
-    self.c2.collect(self.collector)
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'IMPOSSIBLE', authenticated=False)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.TRANSPORT_TAIL_CLOSED,
-                Event.TRANSPORT_ERROR, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testDisallowedPlainClient(self):
-    self.c1.collect(self.collector)
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'PLAIN', authenticated=False)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.TRANSPORT_ERROR,
-                Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testDisallowedPlainServer(self):
-    self.c2.collect(self.collector)
-    self.t1.bind(self.c1)
-    self.t2.bind(self.c2)
-    _testSaslMech(self, 'PLAIN', authenticated=False)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.TRANSPORT_TAIL_CLOSED,
-                Event.TRANSPORT_ERROR, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/soak.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/soak.py b/tests/python/proton_tests/soak.py
deleted file mode 100644
index b7b521c..0000000
--- a/tests/python/proton_tests/soak.py
+++ /dev/null
@@ -1,334 +0,0 @@
-from __future__ import absolute_import
-#
-# 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.
-#
-import os
-import sys
-from .common import Test, Skipped, free_tcp_ports, \
-    MessengerReceiverC, MessengerSenderC, \
-    MessengerReceiverValgrind, MessengerSenderValgrind, \
-    ReactorReceiverC, ReactorSenderC, \
-    ReactorReceiverValgrind, ReactorSenderValgrind, \
-    isSSLPresent
-from proton import *
-
-#
-# Tests that run the apps
-#
-
-class AppTests(Test):
-
-    def __init__(self, *args):
-        Test.__init__(self, *args)
-        self.is_valgrind = False
-
-    def default(self, name, value, **kwargs):
-        if self.is_valgrind:
-            default = kwargs.get("valgrind", value)
-        else:
-            default = value
-        return Test.default(self, name, default, **kwargs)
-
-    @property
-    def iterations(self):
-        return int(self.default("iterations", 2, fast=1, valgrind=2))
-
-    @property
-    def send_count(self):
-        return int(self.default("send_count", 17, fast=1, valgrind=2))
-
-    @property
-    def target_count(self):
-        return int(self.default("target_count", 5, fast=1, valgrind=2))
-
-    @property
-    def send_batch(self):
-        return int(self.default("send_batch", 7, fast=1, valgrind=2))
-
-    @property
-    def forward_count(self):
-        return int(self.default("forward_count", 5, fast=1, valgrind=2))
-
-    @property
-    def port_count(self):
-        return int(self.default("port_count", 3, fast=1, valgrind=2))
-
-    @property
-    def sender_count(self):
-        return int(self.default("sender_count", 3, fast=1, valgrind=2))
-
-    def valgrind_test(self):
-        self.is_valgrind = True
-
-    def setUp(self):
-        self.senders = []
-        self.receivers = []
-
-    def tearDown(self):
-        pass
-
-    def _do_test(self, iterations=1):
-        verbose = self.verbose
-
-        for R in self.receivers:
-            R.start( verbose )
-
-        for j in range(iterations):
-            for S in self.senders:
-                S.start( verbose )
-
-            for S in self.senders:
-                S.wait()
-                #print("SENDER OUTPUT:")
-                #print( S.stdout() )
-                assert S.status() == 0, ("Command '%s' failed status=%d: '%s' '%s'"
-                                         % (str(S.cmdline()),
-                                            S.status(),
-                                            S.stdout(),
-                                            S.stderr()))
-
-        for R in self.receivers:
-            R.wait()
-            #print("RECEIVER OUTPUT")
-            #print( R.stdout() )
-            assert R.status() == 0, ("Command '%s' failed status=%d: '%s' '%s'"
-                                     % (str(R.cmdline()),
-                                        R.status(),
-                                        R.stdout(),
-                                        R.stderr()))
-
-#
-# Traffic passing tests based on the Messenger apps
-#
-
-class MessengerTests(AppTests):
-
-    _timeout = 60
-
-    def _ssl_check(self):
-        if not isSSLPresent():
-            raise Skipped("No SSL libraries found.")
-        if os.name=="nt":
-            raise Skipped("Windows SChannel lacks anonymous cipher support.")
-
-    def __init__(self, *args):
-        AppTests.__init__(self, *args)
-
-    def _do_oneway_test(self, receiver, sender, domain="amqp"):
-        """ Send N messages to a receiver.
-        Parameters:
-        iterations - repeat the senders this many times
-        target_count = # of targets to send to.
-        send_count = # messages sent to each target
-        """
-        iterations = self.iterations
-        send_count = self.send_count
-        target_count = self.target_count
-
-        send_total = send_count * target_count
-        receive_total = send_total * iterations
-
-        port = free_tcp_ports()[0]
-
-        receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port)]
-        receiver.receive_count = receive_total
-        receiver.timeout = MessengerTests._timeout
-        self.receivers.append( receiver )
-
-        sender.targets = ["%s://0.0.0.0:%s/X%d" % (domain, port, j) for j in range(target_count)]
-        sender.send_count = send_total
-        sender.timeout = MessengerTests._timeout
-        self.senders.append( sender )
-
-        self._do_test(iterations)
-
-    def _do_echo_test(self, receiver, sender, domain="amqp"):
-        """ Send N messages to a receiver, which responds to each.
-        Parameters:
-        iterations - repeat the senders this many times
-        target_count - # targets to send to
-        send_count = # messages sent to each target
-        send_batch - wait for replies after this many messages sent
-        """
-        iterations = self.iterations
-        send_count = self.send_count
-        target_count = self.target_count
-        send_batch = self.send_batch
-
-        send_total = send_count * target_count
-        receive_total = send_total * iterations
-
-        port = free_tcp_ports()[0]
-
-        receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port)]
-        receiver.receive_count = receive_total
-        receiver.send_reply = True
-        receiver.timeout = MessengerTests._timeout
-        self.receivers.append( receiver )
-
-        sender.targets = ["%s://0.0.0.0:%s/%dY" % (domain, port, j) for j in range(target_count)]
-        sender.send_count = send_total
-        sender.get_reply = True
-        sender.send_batch = send_batch
-        sender.timeout = MessengerTests._timeout
-        self.senders.append( sender )
-
-        self._do_test(iterations)
-
-    def _do_relay_test(self, receiver, relay, sender, domain="amqp"):
-        """ Send N messages to a receiver, which replies to each and forwards
-        each of them to different receiver.
-        Parameters:
-        iterations - repeat the senders this many times
-        target_count - # targets to send to
-        send_count = # messages sent to each target
-        send_batch - wait for replies after this many messages sent
-        forward_count - forward to this many targets
-        """
-        iterations = self.iterations
-        send_count = self.send_count
-        target_count = self.target_count
-        send_batch = self.send_batch
-        forward_count = self.forward_count
-
-        send_total = send_count * target_count
-        receive_total = send_total * iterations
-
-        port = free_tcp_ports()[0]
-
-        receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port)]
-        receiver.receive_count = receive_total
-        receiver.send_reply = True
-        # forward to 'relay' - uses two links
-        # ## THIS FAILS:
-        # receiver.forwards = ["amqp://Relay/%d" % j for j in range(forward_count)]
-        receiver.forwards = ["%s://Relay" % domain]
-        receiver.timeout = MessengerTests._timeout
-        self.receivers.append( receiver )
-
-        relay.subscriptions = ["%s://0.0.0.0:%s" % (domain, port)]
-        relay.name = "Relay"
-        relay.receive_count = receive_total
-        relay.timeout = MessengerTests._timeout
-        self.receivers.append( relay )
-
-        # send to 'receiver'
-        sender.targets = ["%s://0.0.0.0:%s/X%dY" % (domain, port, j) for j in range(target_count)]
-        sender.send_count = send_total
-        sender.get_reply = True
-        sender.timeout = MessengerTests._timeout
-        self.senders.append( sender )
-
-        self._do_test(iterations)
-
-
-    def _do_star_topology_test(self, r_factory, s_factory, domain="amqp"):
-        """
-        A star-like topology, with a central receiver at the hub, and senders at
-        the spokes.  Each sender will connect to each of the ports the receiver is
-        listening on.  Each sender will then create N links per each connection.
-        Each sender will send X messages per link, waiting for a response.
-        Parameters:
-        iterations - repeat the senders this many times
-        port_count - # of ports the receiver will listen on.  Each sender connects
-                     to all ports.
-        sender_count - # of senders
-        target_count - # of targets per connection
-        send_count - # of messages sent to each target
-        send_batch - # of messages to send before waiting for response
-        """
-        iterations = self.iterations
-        port_count = self.port_count
-        sender_count = self.sender_count
-        target_count = self.target_count
-        send_count = self.send_count
-        send_batch = self.send_batch
-
-        send_total = port_count * target_count * send_count
-        receive_total = send_total * sender_count * iterations
-
-        ports = free_tcp_ports(port_count)
-
-        receiver = r_factory()
-        receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port) for port in ports]
-        receiver.receive_count = receive_total
-        receiver.send_reply = True
-        receiver.timeout = MessengerTests._timeout
-        self.receivers.append( receiver )
-
-        for i in range(sender_count):
-            sender = s_factory()
-            sender.targets = ["%s://0.0.0.0:%s/%d" % (domain, port, j) for port in ports for j in range(target_count)]
-            sender.send_count = send_total
-            sender.send_batch = send_batch
-            sender.get_reply = True
-            sender.timeout = MessengerTests._timeout
-            self.senders.append( sender )
-
-        self._do_test(iterations)
-
-    def test_oneway_C(self):
-        self._do_oneway_test(MessengerReceiverC(), MessengerSenderC())
-
-    def test_oneway_C_SSL(self):
-        self._ssl_check()
-        self._do_oneway_test(MessengerReceiverC(), MessengerSenderC(), "amqps")
-
-    def test_oneway_valgrind(self):
-        self.valgrind_test()
-        self._do_oneway_test(MessengerReceiverValgrind(), MessengerSenderValgrind())
-
-    def test_echo_C(self):
-        self._do_echo_test(MessengerReceiverC(), MessengerSenderC())
-
-    def test_echo_C_SSL(self):
-        self._ssl_check()
-        self._do_echo_test(MessengerReceiverC(), MessengerSenderC(), "amqps")
-
-    def test_echo_valgrind(self):
-        self.valgrind_test()
-        self._do_echo_test(MessengerReceiverValgrind(), MessengerSenderValgrind())
-
-    def test_relay_C(self):
-        self._do_relay_test(MessengerReceiverC(), MessengerReceiverC(), MessengerSenderC())
-
-    def test_relay_C_SSL(self):
-        self._ssl_check()
-        self._do_relay_test(MessengerReceiverC(), MessengerReceiverC(), MessengerSenderC(), "amqps")
-
-    def test_relay_valgrind(self):
-        self.valgrind_test()
-        self._do_relay_test(MessengerReceiverValgrind(), MessengerReceiverValgrind(), MessengerSenderValgrind())
-
-    def test_star_topology_C(self):
-        self._do_star_topology_test( MessengerReceiverC, MessengerSenderC )
-
-    def test_star_topology_C_SSL(self):
-        self._ssl_check()
-        self._do_star_topology_test( MessengerReceiverC, MessengerSenderC, "amqps" )
-
-    def test_star_topology_valgrind(self):
-        self.valgrind_test()
-        self._do_star_topology_test( MessengerReceiverValgrind, MessengerSenderValgrind )
-
-    def test_oneway_reactor(self):
-        self._do_oneway_test(ReactorReceiverC(), ReactorSenderC())
-
-    def test_oneway_reactor_valgrind(self):
-        self.valgrind_test()
-        self._do_oneway_test(ReactorReceiverValgrind(), ReactorSenderValgrind())


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[03/11] qpid-proton git commit: PROTON-1885: [python] move tests/python to python/tests

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/transport.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/transport.py b/tests/python/proton_tests/transport.py
deleted file mode 100644
index 5390d07..0000000
--- a/tests/python/proton_tests/transport.py
+++ /dev/null
@@ -1,393 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-#   http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-import os
-import sys
-from . import common
-from proton import *
-
-
-class Test(common.Test):
-  pass
-
-class ClientTransportTest(Test):
-
-  def setUp(self):
-    self.transport = Transport()
-    self.peer = Transport()
-    self.conn = Connection()
-    self.peer.bind(self.conn)
-
-  def tearDown(self):
-    self.transport = None
-    self.peer = None
-    self.conn = None
-
-  def drain(self):
-    while True:
-      p = self.transport.pending()
-      if p < 0:
-        return
-      elif p > 0:
-        data = self.transport.peek(p)
-        self.peer.push(data)
-        self.transport.pop(len(data))
-      else:
-        assert False
-
-  def assert_error(self, name):
-    assert self.conn.remote_container is None, self.conn.remote_container
-    self.drain()
-    # verify that we received an open frame
-    assert self.conn.remote_container is not None, self.conn.remote_container
-    # verify that we received a close frame
-    assert self.conn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_CLOSED, self.conn.state
-    # verify that a framing error was reported
-    assert self.conn.remote_condition.name == name, self.conn.remote_condition
-
-  def testEOS(self):
-    self.transport.push(b"") # should be a noop
-    self.transport.close_tail() # should result in framing error
-    self.assert_error(u'amqp:connection:framing-error')
-
-  def testPartial(self):
-    self.transport.push(b"AMQ") # partial header
-    self.transport.close_tail() # should result in framing error
-    self.assert_error(u'amqp:connection:framing-error')
-
-  def testGarbage(self, garbage=b"GARBAGE_"):
-    self.transport.push(garbage)
-    self.assert_error(u'amqp:connection:framing-error')
-    assert self.transport.pending() < 0
-    self.transport.close_tail()
-    assert self.transport.pending() < 0
-
-  def testSmallGarbage(self):
-    self.testGarbage(b"XXX")
-
-  def testBigGarbage(self):
-    self.testGarbage(b"GARBAGE_XXX")
-
-  def testHeader(self):
-    self.transport.push(b"AMQP\x00\x01\x00\x00")
-    self.transport.close_tail()
-    self.assert_error(u'amqp:connection:framing-error')
-
-  def testHeaderBadDOFF1(self):
-    """Verify doff > size error"""
-    self.testGarbage(b"AMQP\x00\x01\x00\x00\x00\x00\x00\x08\x08\x00\x00\x00")
-
-  def testHeaderBadDOFF2(self):
-    """Verify doff < 2 error"""
-    self.testGarbage(b"AMQP\x00\x01\x00\x00\x00\x00\x00\x08\x01\x00\x00\x00")
-
-  def testHeaderBadSize(self):
-    """Verify size > max_frame_size error"""
-    self.transport.max_frame_size = 512
-    self.testGarbage(b"AMQP\x00\x01\x00\x00\x00\x00\x02\x01\x02\x00\x00\x00")
-
-  def testProtocolNotSupported(self):
-    self.transport.push(b"AMQP\x01\x01\x0a\x00")
-    p = self.transport.pending()
-    assert p >= 8, p
-    bytes = self.transport.peek(p)
-    assert bytes[:8] == b"AMQP\x00\x01\x00\x00"
-    self.transport.pop(p)
-    self.drain()
-    assert self.transport.closed
-
-  def testPeek(self):
-    out = self.transport.peek(1024)
-    assert out is not None
-
-  def testBindAfterOpen(self):
-    conn = Connection()
-    ssn = conn.session()
-    conn.open()
-    ssn.open()
-    conn.container = "test-container"
-    conn.hostname = "test-hostname"
-    trn = Transport()
-    trn.bind(conn)
-    out = trn.peek(1024)
-    assert b"test-container" in out, repr(out)
-    assert b"test-hostname" in out, repr(out)
-    self.transport.push(out)
-
-    c = Connection()
-    assert c.remote_container == None
-    assert c.remote_hostname == None
-    assert c.session_head(0) == None
-    self.transport.bind(c)
-    assert c.remote_container == "test-container"
-    assert c.remote_hostname == "test-hostname"
-    assert c.session_head(0) != None
-
-  def testCloseHead(self):
-    n = self.transport.pending()
-    assert n > 0, n
-    try:
-      self.transport.close_head()
-    except TransportException:
-      e = sys.exc_info()[1]
-      assert "aborted" in str(e), str(e)
-    n = self.transport.pending()
-    assert n < 0, n
-
-  def testCloseTail(self):
-    n = self.transport.capacity()
-    assert n > 0, n
-    try:
-      self.transport.close_tail()
-    except TransportException:
-      e = sys.exc_info()[1]
-      assert "aborted" in str(e), str(e)
-    n = self.transport.capacity()
-    assert n < 0, n
-
-  def testUnpairedPop(self):
-    conn = Connection()
-    self.transport.bind(conn)
-
-    conn.hostname = "hostname"
-    conn.open()
-
-    dat1 = self.transport.peek(1024)
-
-    ssn = conn.session()
-    ssn.open()
-
-    dat2 = self.transport.peek(1024)
-
-    assert dat2[:len(dat1)] == dat1
-
-    snd = ssn.sender("sender")
-    snd.open()
-
-    self.transport.pop(len(dat1))
-    self.transport.pop(len(dat2) - len(dat1))
-    dat3 = self.transport.peek(1024)
-    self.transport.pop(len(dat3))
-    assert self.transport.peek(1024) == b""
-
-    self.peer.push(dat1)
-    self.peer.push(dat2[len(dat1):])
-    self.peer.push(dat3)
-
-class ServerTransportTest(Test):
-
-  def setUp(self):
-    self.transport = Transport(Transport.SERVER)
-    self.peer = Transport()
-    self.conn = Connection()
-    self.peer.bind(self.conn)
-
-  def tearDOwn(self):
-    self.transport = None
-    self.peer = None
-    self.conn = None
-
-  def drain(self):
-    while True:
-      p = self.transport.pending()
-      if p < 0:
-        return
-      elif p > 0:
-        bytes = self.transport.peek(p)
-        self.peer.push(bytes)
-        self.transport.pop(len(bytes))
-      else:
-        assert False
-
-  def assert_error(self, name):
-    assert self.conn.remote_container is None, self.conn.remote_container
-    self.drain()
-    # verify that we received an open frame
-    assert self.conn.remote_container is not None, self.conn.remote_container
-    # verify that we received a close frame
-    assert self.conn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_CLOSED, self.conn.state
-    # verify that a framing error was reported
-    assert self.conn.remote_condition.name == name, self.conn.remote_condition
-
-  # TODO: This may no longer be testing anything
-  def testEOS(self):
-    self.transport.push(b"") # should be a noop
-    self.transport.close_tail()
-    p = self.transport.pending()
-    self.drain()
-    assert self.transport.closed
-
-  def testPartial(self):
-    self.transport.push(b"AMQ") # partial header
-    self.transport.close_tail()
-    p = self.transport.pending()
-    assert p >= 8, p
-    bytes = self.transport.peek(p)
-    assert bytes[:8] == b"AMQP\x00\x01\x00\x00"
-    self.transport.pop(p)
-    self.drain()
-    assert self.transport.closed
-
-  def testGarbage(self, garbage=b"GARBAGE_"):
-    self.transport.push(garbage)
-    p = self.transport.pending()
-    assert p >= 8, p
-    bytes = self.transport.peek(p)
-    assert bytes[:8] == b"AMQP\x00\x01\x00\x00"
-    self.transport.pop(p)
-    self.drain()
-    assert self.transport.closed
-
-  def testSmallGarbage(self):
-    self.testGarbage(b"XXX")
-
-  def testBigGarbage(self):
-    self.testGarbage(b"GARBAGE_XXX")
-
-  def testHeader(self):
-    self.transport.push(b"AMQP\x00\x01\x00\x00")
-    self.transport.close_tail()
-    self.assert_error(u'amqp:connection:framing-error')
-
-  def testProtocolNotSupported(self):
-    self.transport.push(b"AMQP\x01\x01\x0a\x00")
-    p = self.transport.pending()
-    assert p >= 8, p
-    bytes = self.transport.peek(p)
-    assert bytes[:8] == b"AMQP\x00\x01\x00\x00"
-    self.transport.pop(p)
-    self.drain()
-    assert self.transport.closed
-
-  def testPeek(self):
-    out = self.transport.peek(1024)
-    assert out is not None
-
-  def testBindAfterOpen(self):
-    conn = Connection()
-    ssn = conn.session()
-    conn.open()
-    ssn.open()
-    conn.container = "test-container"
-    conn.hostname = "test-hostname"
-    trn = Transport()
-    trn.bind(conn)
-    out = trn.peek(1024)
-    assert b"test-container" in out, repr(out)
-    assert b"test-hostname" in out, repr(out)
-    self.transport.push(out)
-
-    c = Connection()
-    assert c.remote_container == None
-    assert c.remote_hostname == None
-    assert c.session_head(0) == None
-    self.transport.bind(c)
-    assert c.remote_container == "test-container"
-    assert c.remote_hostname == "test-hostname"
-    assert c.session_head(0) != None
-
-  def testCloseHead(self):
-    n = self.transport.pending()
-    assert n >= 0, n
-    try:
-      self.transport.close_head()
-    except TransportException:
-      e = sys.exc_info()[1]
-      assert "aborted" in str(e), str(e)
-    n = self.transport.pending()
-    assert n < 0, n
-
-  def testCloseTail(self):
-    n = self.transport.capacity()
-    assert n > 0, n
-    try:
-      self.transport.close_tail()
-    except TransportException:
-      e = sys.exc_info()[1]
-      assert "aborted" in str(e), str(e)
-    n = self.transport.capacity()
-    assert n < 0, n
-
-  def testUnpairedPop(self):
-    conn = Connection()
-    self.transport.bind(conn)
-
-    conn.hostname = "hostname"
-    conn.open()
-
-    dat1 = self.transport.peek(1024)
-
-    ssn = conn.session()
-    ssn.open()
-
-    dat2 = self.transport.peek(1024)
-
-    assert dat2[:len(dat1)] == dat1
-
-    snd = ssn.sender("sender")
-    snd.open()
-
-    self.transport.pop(len(dat1))
-    self.transport.pop(len(dat2) - len(dat1))
-    dat3 = self.transport.peek(1024)
-    self.transport.pop(len(dat3))
-    assert self.transport.peek(1024) == b""
-
-    self.peer.push(dat1)
-    self.peer.push(dat2[len(dat1):])
-    self.peer.push(dat3)
-
-  def testEOSAfterSASL(self):
-    self.transport.sasl().allowed_mechs('ANONYMOUS')
-
-    self.peer.sasl().allowed_mechs('ANONYMOUS')
-
-    # this should send over the sasl header plus a sasl-init set up
-    # for anonymous
-    p = self.peer.pending()
-    self.transport.push(self.peer.peek(p))
-    self.peer.pop(p)
-
-    # now we send EOS
-    self.transport.close_tail()
-
-    # the server may send an error back
-    p = self.transport.pending()
-    while p>0:
-      self.peer.push(self.transport.peek(p))
-      self.transport.pop(p)
-      p = self.transport.pending()
-
-    # server closed
-    assert self.transport.pending() < 0
-
-class LogTest(Test):
-
-  def testTracer(self):
-    t = Transport()
-    assert t.tracer is None
-    messages = []
-    def tracer(transport, message):
-      messages.append((transport, message))
-    t.tracer = tracer
-    assert t.tracer is tracer
-    t.log("one")
-    t.log("two")
-    t.log("three")
-    assert messages == [(t, "one"), (t, "two"), (t, "three")], messages

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/url.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/url.py b/tests/python/proton_tests/url.py
deleted file mode 100644
index b44699a..0000000
--- a/tests/python/proton_tests/url.py
+++ /dev/null
@@ -1,147 +0,0 @@
-from __future__ import absolute_import
-#
-# 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.
-#
-
-
-from . import common
-from proton import Url
-
-class UrlTest(common.Test):
-    def assertEqual(self, a, b):
-        assert a == b, "%s != %s" % (a, b)
-
-    def assertNotEqual(self, a, b):
-        assert a != b, "%s == %s" % (a, b)
-
-    def assertUrl(self, u, scheme, username, password, host, port, path):
-        self.assertEqual((u.scheme, u.username, u.password, u.host, u.port, u.path),
-                         (scheme, username, password, host, port, path))
-
-    def testUrl(self):
-        url = Url('amqp://me:secret@myhost:1234/foobar')
-        self.assertEqual(str(url), "amqp://me:secret@myhost:1234/foobar")
-        self.assertUrl(url, 'amqp', 'me', 'secret', 'myhost', 1234, 'foobar')
-        self.assertEqual(str(url), "amqp://me:secret@myhost:1234/foobar")
-
-    def testDefaults(self):
-        # Check that we allow None for scheme, port
-        url = Url(username='me', password='secret', host='myhost', path='foobar', defaults=False)
-        self.assertEqual(str(url), "//me:secret@myhost/foobar")
-        self.assertUrl(url, None, 'me', 'secret', 'myhost', None, 'foobar')
-
-        self.assertEqual(str(Url("amqp://me:secret@myhost/foobar")),
-                         "amqp://me:secret@myhost:amqp/foobar")
-
-        # Empty string vs. None for path
-        self.assertEqual(Url("myhost/").path, "")
-        assert Url("myhost", defaults=False).path is None
-
-        # Expanding abbreviated url strings.
-        for s, u in [
-            ("", "amqp://0.0.0.0:amqp"),
-            ("foo", "amqp://foo:amqp"),
-            (":1234", "amqp://0.0.0.0:1234"),
-            ("/path", "amqp://0.0.0.0:amqp/path"),
-            ("user@host/topic://test", "amqp://user@host:amqp/topic://test"),
-            ("user@host:3456", "amqp://user@host:3456"),
-            ("user:pass@host/topic://test", "amqp://user:pass@host:amqp/topic://test")
-        ]: self.assertEqual(str(Url(s)), u)
-
-    def assertPort(self, port, portint, portstr):
-        self.assertEqual((port, port), (portint, portstr))
-        self.assertEqual((int(port), str(port)), (portint, portstr))
-
-    def testPort(self):
-        self.assertPort(Url.Port('amqp'), 5672, 'amqp')
-        self.assertPort(Url.Port(5672), 5672, '5672')
-        self.assertPort(Url.Port(5671), 5671, '5671')
-        self.assertEqual(Url.Port(5671)+1, 5672) # Treat as int
-        self.assertEqual(str(Url.Port(5672)), '5672')
-
-        self.assertPort(Url.Port(Url.Port('amqp')), 5672, 'amqp')
-        self.assertPort(Url.Port(Url.Port(5672)), 5672, '5672')
-
-        try:
-            Url.Port('xxx')
-            assert False, "Expected ValueError"
-        except ValueError: pass
-
-        self.assertEqual(str(Url("host:amqp", defaults=False)), "//host:amqp")
-        self.assertEqual(Url("host:amqp", defaults=False).port, 5672)
-
-    def testArgs(self):
-        u = Url("amqp://u:p@host:amqp/path", scheme='foo', host='bar', port=1234, path='garden', defaults=False)
-        self.assertUrl(u, 'foo', 'u', 'p', 'bar', 1234, 'garden')
-        u = Url(defaults=False)
-        self.assertUrl(u, None, None, None, None, None, None)
-
-    def assertRaises(self, exception, function, *args, **kwargs):
-        try:
-            function(*args, **kwargs)
-            assert False, "Expected exception %s" % exception.__name__
-        except exception: pass
-
-    def testMissing(self):
-        self.assertUrl(Url(defaults=False), None, None, None, None, None, None)
-        self.assertUrl(Url('amqp://', defaults=False), 'amqp', None, None, None, None, None)
-        self.assertUrl(Url('username@', defaults=False), None, 'username', None, None, None, None)
-        self.assertUrl(Url(':pass@', defaults=False), None, '', 'pass', None, None, None)
-        self.assertUrl(Url('host', defaults=False), None, None, None, 'host', None, None)
-        self.assertUrl(Url(':1234', defaults=False), None, None, None, None, 1234, None)
-        self.assertUrl(Url('/path', defaults=False), None, None, None, None, None, 'path')
-
-        for s, full in [
-            ('amqp://', 'amqp://'),
-            ('username@','//username@'),
-            (':pass@', '//:pass@'),
-            (':1234', '//:1234'),
-            ('/path','/path')
-        ]:
-            self.assertEqual(str(Url(s, defaults=False)), full)
-
-        for s, full in [
-                ('amqp://', 'amqp://0.0.0.0:amqp'),
-                ('username@', 'amqp://username@0.0.0.0:amqp'),
-                (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
-                (':1234', 'amqp://0.0.0.0:1234'),
-                ('/path', 'amqp://0.0.0.0:amqp/path'),
-                ('foo/path', 'amqp://foo:amqp/path'),
-                (':1234/path', 'amqp://0.0.0.0:1234/path')
-        ]:
-            self.assertEqual(str(Url(s)), full)
-
-    def testAmqps(self):
-        # Scheme defaults
-        self.assertEqual(str(Url("me:secret@myhost/foobar")),
-                         "amqp://me:secret@myhost:amqp/foobar")
-        # Correct port for amqps vs. amqps
-        self.assertEqual(str(Url("amqps://me:secret@myhost/foobar")),
-                         "amqps://me:secret@myhost:amqps/foobar")
-
-        self.assertPort(Url.Port('amqps'), 5671, 'amqps')
-        self.assertEqual(str(Url("host:amqps", defaults=False)), "//host:amqps")
-        self.assertEqual(Url("host:amqps", defaults=False).port, 5671)
-
-    def testEqual(self):
-        self.assertEqual(Url("foo/path"), 'amqp://foo:amqp/path')
-        self.assertEqual('amqp://foo:amqp/path', Url("foo/path"))
-        self.assertEqual(Url("foo/path"), Url("foo/path"))
-        self.assertNotEqual(Url("foo/path"), 'xamqp://foo:amqp/path')
-        self.assertNotEqual('xamqp://foo:amqp/path', Url("foo/path"))
-        self.assertNotEqual(Url("foo/path"), Url("bar/path"))

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/utils.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/utils.py b/tests/python/proton_tests/utils.py
deleted file mode 100644
index 1f20bba..0000000
--- a/tests/python/proton_tests/utils.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-import os, time, sys
-from threading import Thread, Event
-from unittest import TestCase
-from proton_tests.common import Test, free_tcp_port
-from copy import copy
-from proton import Message, Url, generate_uuid, Array, UNDESCRIBED, Data, symbol, ConnectionException, ProtonException
-from proton.handlers import MessagingHandler
-from proton.reactor import Container
-from proton.utils import SyncRequestResponse, BlockingConnection
-from .common import Skipped, ensureCanTestExtendedSASL
-CONNECTION_PROPERTIES={u'connection': u'properties'}
-OFFERED_CAPABILITIES = Array(UNDESCRIBED, Data.SYMBOL, symbol("O_one"), symbol("O_two"), symbol("O_three"))
-DESIRED_CAPABILITIES = Array(UNDESCRIBED, Data.SYMBOL, symbol("D_one"), symbol("D_two"), symbol("D_three"))
-ANONYMOUS='ANONYMOUS'
-EXTERNAL='EXTERNAL'
-
-class EchoServer(MessagingHandler, Thread):
-    """
-    Simple echo server that echos messages to their reply-to. Runs in a thread.
-    Will only accept a single connection and shut down when that connection closes.
-    """
-
-    def __init__(self, url, timeout):
-        MessagingHandler.__init__(self)
-        Thread.__init__(self)
-        self.daemon = True
-        self.timeout = timeout
-        self.url = url
-        self.senders = {}
-        self.container = None
-        self.event = Event()
-
-    def on_start(self, event):
-        self.acceptor = event.container.listen(self.url)
-        self.container = event.container
-        self.event.set()
-
-    def on_link_opening(self, event):
-        if event.link.is_sender:
-            if event.link.remote_source and event.link.remote_source.dynamic:
-                event.link.source.address = str(generate_uuid())
-                self.senders[event.link.source.address] = event.link
-
-    def on_message(self, event):
-        m = event.message
-        sender = self.senders.get(m.reply_to)
-        if sender:
-            reply = Message(address=m.reply_to, body=m.body, correlation_id=m.correlation_id)
-            sender.send(reply)
-
-    def on_connection_closing(self, event):
-        self.acceptor.close()
-
-    def on_transport_error(self, event):
-        self.acceptor.close()
-
-    def run(self):
-        Container(self).run()
-
-    def wait(self):
-        self.event.wait(self.timeout)
-
-
-class ConnPropertiesServer(EchoServer):
-     def __init__(self, url, timeout):
-        EchoServer.__init__(self, url, timeout)
-        self.properties_received = False
-        self.offered_capabilities_received = False
-        self.desired_capabilities_received = False
-
-     def on_connection_opening(self, event):
-        conn = event.connection
-
-        if conn.remote_properties == CONNECTION_PROPERTIES:
-            self.properties_received = True
-        if conn.remote_offered_capabilities == OFFERED_CAPABILITIES:
-            self.offered_capabilities_received = True
-        if conn.remote_desired_capabilities == DESIRED_CAPABILITIES:
-            self.desired_capabilities_received = True
-
-class SyncRequestResponseTest(Test):
-    """Test SyncRequestResponse"""
-
-    def test_request_response(self):
-        ensureCanTestExtendedSASL()
-        def test(name, address="x"):
-            for i in range(5):
-                body="%s%s" % (name, i)
-                response = client.call(Message(address=address, body=body))
-                self.assertEquals(response.address, client.reply_to)
-                self.assertEquals(response.body, body)
-
-        server = EchoServer(Url(host="127.0.0.1", port=free_tcp_port()), self.timeout)
-        server.start()
-        server.wait()
-        connection = BlockingConnection(server.url, timeout=self.timeout)
-        client = SyncRequestResponse(connection)
-        try:
-            test("foo")         # Simple request/resposne
-        finally:
-            client.connection.close()
-        server.join(timeout=self.timeout)
-
-
-    def test_connection_properties(self):
-        ensureCanTestExtendedSASL()
-        server = ConnPropertiesServer(Url(host="127.0.0.1", port=free_tcp_port()), timeout=self.timeout)
-        server.start()
-        server.wait()
-        connection = BlockingConnection(server.url, timeout=self.timeout, properties=CONNECTION_PROPERTIES, offered_capabilities=OFFERED_CAPABILITIES, desired_capabilities=DESIRED_CAPABILITIES)
-        client = SyncRequestResponse(connection)
-        client.connection.close()
-        server.join(timeout=self.timeout)
-        self.assertEquals(server.properties_received, True)
-        self.assertEquals(server.offered_capabilities_received, True)
-        self.assertEquals(server.desired_capabilities_received, True)
-
-    def test_allowed_mechs_external(self):
-        # All this test does it make sure that if we pass allowed_mechs to BlockingConnection, it is actually used.
-        port = free_tcp_port()
-        server = ConnPropertiesServer(Url(host="127.0.0.1", port=port), timeout=self.timeout)
-        server.start()
-        server.wait()
-        try:
-            # This will cause an exception because we are specifying allowed_mechs as EXTERNAL. The SASL handshake will fail because the server is not setup to handle EXTERNAL
-            connection = BlockingConnection(server.url, timeout=self.timeout, properties=CONNECTION_PROPERTIES, offered_capabilities=OFFERED_CAPABILITIES, desired_capabilities=DESIRED_CAPABILITIES, allowed_mechs=EXTERNAL)
-            self.fail("Expected ConnectionException")
-        except ConnectionException as e:
-            self.assertTrue('amqp:unauthorized-access' in str(e), "expected unauthorized-access")
-        server.join(timeout=self.timeout)
-
-    def test_allowed_mechs_anonymous(self):
-        # All this test does it make sure that if we pass allowed_mechs to BlockingConnection, it is actually used.
-        server = ConnPropertiesServer(Url(host="127.0.0.1", port=free_tcp_port()), timeout=self.timeout)
-        server.start()
-        server.wait()
-        # An ANONYMOUS allowed_mechs will work, anonymous connections are allowed by ConnPropertiesServer
-        connection = BlockingConnection(server.url, timeout=self.timeout, properties=CONNECTION_PROPERTIES, offered_capabilities=OFFERED_CAPABILITIES, desired_capabilities=DESIRED_CAPABILITIES, allowed_mechs=ANONYMOUS)
-        client = SyncRequestResponse(connection)
-        client.connection.close()
-        server.join(timeout=self.timeout)
-        self.assertEquals(server.properties_received, True)
-        self.assertEquals(server.offered_capabilities_received, True)
-        self.assertEquals(server.desired_capabilities_received, True)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/tox-blacklist
----------------------------------------------------------------------
diff --git a/tests/python/tox-blacklist b/tests/python/tox-blacklist
deleted file mode 100644
index 3c10c71..0000000
--- a/tests/python/tox-blacklist
+++ /dev/null
@@ -1,13 +0,0 @@
-# Running *all* the python tests under tox is redundant as this is
-# already done by the python-test suite.
-# This file contains a list of the longer running tests that can be
-# skipped in order to speed up the tox test run
-
-proton_tests.soak.*
-proton_tests.engine.ServerTest.testIdleTimeout
-proton_tests.engine.ServerTest.testKeepalive
-proton_tests.messenger.IdleTimeoutTest.testIdleTimeout
-proton_tests.messenger.MessengerTest.testCreditBlockingRebalance
-proton_tests.messenger.NBMessengerTest.testCreditReplenish
-proton_tests.messenger.NBMessengerTest.testRecvBeforeSubscribe
-


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[08/11] qpid-proton git commit: PROTON-1885: [python] move tests/python to python/tests

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl.py b/python/tests/proton_tests/ssl.py
new file mode 100644
index 0000000..da237f9
--- /dev/null
+++ b/python/tests/proton_tests/ssl.py
@@ -0,0 +1,936 @@
+from __future__ import absolute_import
+#
+# 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.
+#
+
+import os
+from . import common
+import random
+import string
+import subprocess
+import sys
+from proton import *
+from .common import Skipped, pump
+
+
+def _testpath(file):
+    """ Set the full path to the certificate,keyfile, etc. for the test.
+    """
+    if os.name=="nt":
+        if file.find("private-key")!=-1:
+            # The private key is not in a separate store
+            return None
+        # Substitute pkcs#12 equivalent for the CA/key store
+        if file.endswith(".pem"):
+            file = file[:-4] + ".p12"
+    return os.path.join(os.path.dirname(__file__),
+                        "ssl_db/%s" % file)
+
+class SslTest(common.Test):
+
+    def __init__(self, *args):
+        common.Test.__init__(self, *args)
+        self._testpath = _testpath
+
+    def setUp(self):
+        if not common.isSSLPresent():
+            raise Skipped("No SSL libraries found.")
+        self.server_domain = SSLDomain(SSLDomain.MODE_SERVER)
+        self.client_domain = SSLDomain(SSLDomain.MODE_CLIENT)
+
+    def tearDown(self):
+        self.server_domain = None
+        self.client_domain = None
+
+    class SslTestConnection(object):
+        """ Represents a single SSL connection.
+        """
+        def __init__(self, domain=None, mode=Transport.CLIENT,
+                     session_details=None, conn_hostname=None,
+                     ssl_peername=None):
+            if not common.isSSLPresent():
+                raise Skipped("No SSL libraries found.")
+
+            self.ssl = None
+            self.domain = domain
+            self.transport = Transport(mode)
+            self.connection = Connection()
+            if conn_hostname:
+                self.connection.hostname = conn_hostname
+            if domain:
+                self.ssl = SSL( self.transport, self.domain, session_details )
+                if ssl_peername:
+                    self.ssl.peer_hostname = ssl_peername
+            # bind last, after all configuration complete:
+            self.transport.bind(self.connection)
+
+    def _pump(self, ssl_client, ssl_server, buffer_size=1024):
+        pump(ssl_client.transport, ssl_server.transport, buffer_size)
+
+    def _do_handshake(self, client, server):
+        """ Attempt to connect client to server. Will throw a TransportException if the SSL
+        handshake fails.
+        """
+        client.connection.open()
+        server.connection.open()
+        self._pump(client, server)
+        if client.transport.closed:
+            return
+        assert client.ssl.protocol_name() is not None
+        client.connection.close()
+        server.connection.close()
+        self._pump(client, server)
+
+    def test_defaults(self):
+        if os.name=="nt":
+            raise Skipped("Windows SChannel lacks anonymous cipher support.")
+        """ By default, both the server and the client support anonymous
+        ciphers - they should connect without need for a certificate.
+        """
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        # check that no SSL connection exists
+        assert not server.ssl.cipher_name()
+        assert not client.ssl.protocol_name()
+
+        #client.transport.trace(Transport.TRACE_DRV)
+        #server.transport.trace(Transport.TRACE_DRV)
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+
+        # now SSL should be active
+        assert server.ssl.cipher_name() is not None
+        assert client.ssl.protocol_name() is not None
+
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+    def test_ssl_with_small_buffer(self):
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.connection.open()
+        server.connection.open()
+
+        small_buffer_size = 1
+        self._pump( client, server, small_buffer_size )
+
+        assert client.ssl.protocol_name() is not None
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+
+    def test_server_certificate(self):
+        """ Test that anonymous clients can still connect to a server that has
+        a certificate configured.
+        """
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert client.ssl.protocol_name() is not None
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+    def test_server_authentication(self):
+        """ Simple SSL connection with authentication of the server
+        """
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert client.ssl.protocol_name() is not None
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+    def test_certificate_fingerprint_and_subfields(self):
+        if os.name=="nt":
+            raise Skipped("Windows support for certificate fingerprint and subfield not implemented yet")
+
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
+                                                    self._testpath("ca-certificate.pem") )
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+
+        # give the client a certificate, but let's not require server authentication
+        self.client_domain.set_credentials(self._testpath("client-certificate1.pem"),
+                                           self._testpath("client-private-key1.pem"),
+                                           "client-password")
+        self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+
+        # Test the subject subfields
+        self.assertEqual("Client", server.ssl.get_cert_organization())
+        self.assertEqual("Dev", server.ssl.get_cert_organization_unit())
+        self.assertEqual("ST", server.ssl.get_cert_state_or_province())
+        self.assertEqual("US", server.ssl.get_cert_country())
+        self.assertEqual("City", server.ssl.get_cert_locality_or_city())
+        self.assertEqual("O=Server,CN=A1.Good.Server.domain.com", client.ssl.get_cert_subject())
+        self.assertEqual("O=Client,CN=127.0.0.1,C=US,ST=ST,L=City,OU=Dev", server.ssl.get_cert_subject())
+
+        self.assertEqual("f78f03ec31317c213dcf607c095242adbf067824", server.ssl.get_cert_fingerprint_sha1())
+        self.assertEqual("3836fd0d7bbc155158997ff336de29545cc1ce4137f8419062ceb8b50fd7a6f9", server.ssl.get_cert_fingerprint_sha256())
+        self.assertEqual("a8390634eb10c7a12ba3ce0837001bc6ae78c7690984f4788cf4430acdb496d5d9e02c8ec39219f5c4dcd908c34861d09481c2faf53b4ccc95dac60e623165c4",
+                         server.ssl.get_cert_fingerprint_sha512())
+        self.assertEqual("32b7bc119f61c71d368caaf9a6bf58b2", server.ssl.get_cert_fingerprint_md5())
+
+        # Test the various fingerprint algorithms
+        self.assertEqual("0aab5922c8657a7fb78402b79379506d3d7806ce", client.ssl.get_cert_fingerprint_sha1())
+        self.assertEqual("de5e0c4097f841815a769ce1a30dbe912b83711438a5aaf50001da23cee5a8a8", client.ssl.get_cert_fingerprint_sha256())
+        self.assertEqual("d0aceeb68ab9de57c9e1c21a43a4511c54ec94011e770a523a6352b1374f59c8b58adc93d5cad6f25aa125b5934309a61a25e74a5d5e0cb40b07c7468615944c",
+                         client.ssl.get_cert_fingerprint_sha512())
+        self.assertEqual("ae0ebcebc1f970fb696ef9f56e3235da", client.ssl.get_cert_fingerprint_md5())
+
+        self.assertEqual(None, client.ssl.get_cert_fingerprint(21, SSL.SHA1)) # Should be at least 41
+        self.assertEqual(None, client.ssl.get_cert_fingerprint(50, SSL.SHA256)) # Should be at least 65
+        self.assertEqual(None, client.ssl.get_cert_fingerprint(128, SSL.SHA512)) # Should be at least 129
+        self.assertEqual(None, client.ssl.get_cert_fingerprint(10, SSL.MD5)) # Should be at least 33
+        self.assertEqual(None, client.ssl._get_cert_subject_unknown_subfield())
+
+        self.assertNotEqual(None, client.ssl.get_cert_fingerprint(50, SSL.SHA1)) # Should be at least 41
+        self.assertNotEqual(None, client.ssl.get_cert_fingerprint(70, SSL.SHA256)) # Should be at least 65
+        self.assertNotEqual(None, client.ssl.get_cert_fingerprint(130, SSL.SHA512)) # Should be at least 129
+        self.assertNotEqual(None, client.ssl.get_cert_fingerprint(35, SSL.MD5)) # Should be at least 33
+        self.assertEqual(None, client.ssl._get_cert_fingerprint_unknown_hash_alg())
+
+    def test_client_authentication(self):
+        """ Force the client to authenticate.
+        """
+        # note: when requesting client auth, the server _must_ send its
+        # certificate, so make sure we configure one!
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
+                                                    self._testpath("ca-certificate.pem") )
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+
+        # give the client a certificate, but let's not require server authentication
+        self.client_domain.set_credentials(self._testpath("client-certificate.pem"),
+                                           self._testpath("client-private-key.pem"),
+                                           "client-password")
+        self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+
+        assert client.ssl.protocol_name() is not None
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+    def test_client_authentication_fail_bad_cert(self):
+        """ Ensure that the server can detect a bad client certificate.
+        """
+        # note: when requesting client auth, the server _must_ send its
+        # certificate, so make sure we configure one!
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
+                                                    self._testpath("ca-certificate.pem") )
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+
+        self.client_domain.set_credentials(self._testpath("bad-server-certificate.pem"),
+                                           self._testpath("bad-server-private-key.pem"),
+                                           "server-password")
+        self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert client.transport.closed
+        assert server.transport.closed
+        assert client.connection.state & Endpoint.REMOTE_UNINIT
+        assert server.connection.state & Endpoint.REMOTE_UNINIT
+
+    def test_client_authentication_fail_no_cert(self):
+        """ Ensure that the server will fail a client that does not provide a
+        certificate.
+        """
+        # note: when requesting client auth, the server _must_ send its
+        # certificate, so make sure we configure one!
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
+                                                    self._testpath("ca-certificate.pem") )
+        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()
+        server.connection.open()
+        self._pump( client, server )
+        assert client.transport.closed
+        assert server.transport.closed
+        assert client.connection.state & Endpoint.REMOTE_UNINIT
+        assert server.connection.state & Endpoint.REMOTE_UNINIT
+
+    def test_client_server_authentication(self):
+        """ Require both client and server to mutually identify themselves.
+        """
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
+                                                    self._testpath("ca-certificate.pem") )
+
+        self.client_domain.set_credentials(self._testpath("client-certificate.pem"),
+                                           self._testpath("client-private-key.pem"),
+                                           "client-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert client.ssl.protocol_name() is not None
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+    def test_server_only_authentication(self):
+        """ Client verifies server, but server does not verify client.
+        """
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
+
+        self.client_domain.set_credentials(self._testpath("client-certificate.pem"),
+                                           self._testpath("client-private-key.pem"),
+                                           "client-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert client.ssl.protocol_name() is not None
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+    def test_bad_server_certificate(self):
+        """ A server with a self-signed certificate that is not trusted by the
+        client.  The client should reject the server.
+        """
+        self.server_domain.set_credentials(self._testpath("bad-server-certificate.pem"),
+                                           self._testpath("bad-server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
+
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert client.transport.closed
+        assert server.transport.closed
+        assert client.connection.state & Endpoint.REMOTE_UNINIT
+        assert server.connection.state & Endpoint.REMOTE_UNINIT
+
+        del server
+        del client
+
+        # now re-try with a client that does not require peer verification
+        self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
+
+        client = SslTest.SslTestConnection( self.client_domain )
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert client.ssl.protocol_name() is not None
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+    def test_allow_unsecured_client_which_connects_unsecured(self):
+        """ Server allows an unsecured client to connect if configured.
+        """
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
+                                                    self._testpath("ca-certificate.pem") )
+        # allow unsecured clients on this connection
+        self.server_domain.allow_unsecured_client()
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+
+        # non-ssl connection
+        client = SslTest.SslTestConnection()
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert server.ssl.protocol_name() is None
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+    def test_allow_unsecured_client_which_connects_secured(self):
+        """ As per test_allow_unsecured_client_which_connects_unsecured
+            but client actually uses SSL
+        """
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
+                                                    self._testpath("ca-certificate.pem") )
+
+        self.client_domain.set_credentials(self._testpath("client-certificate.pem"),
+                                           self._testpath("client-private-key.pem"),
+                                           "client-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
+
+        # allow unsecured clients on this connection
+        #self.server_domain.allow_unsecured_client()
+
+        # client uses ssl. Server should detect this.
+        client = SslTest.SslTestConnection( self.client_domain )
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert server.ssl.protocol_name() is not None
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+
+    def test_disallow_unsecured_client(self):
+        """ Non-SSL Client is disallowed from connecting to server.
+        """
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+
+        # non-ssl connection
+        client = SslTest.SslTestConnection()
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert client.transport.closed
+        assert server.transport.closed
+        assert client.connection.state & Endpoint.REMOTE_UNINIT
+        assert server.connection.state & Endpoint.REMOTE_UNINIT
+
+    def test_session_resume(self):
+        """ Test resume of client session.
+        """
+        if os.name=="nt":
+            raise Skipped("Windows SChannel session resume not yet implemented.")
+
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
+
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
+
+        # details will be used in initial and subsequent connections to allow session to be resumed
+        initial_session_details = SSLSessionDetails("my-session-id")
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain, session_details=initial_session_details )
+
+        # bring up the connection and store its state
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert client.ssl.protocol_name() is not None
+
+        # cleanly shutdown the connection
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+        # destroy the existing clients
+        del client
+        del server
+
+        # now create a new set of connections, use last session id
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        # provide the details of the last session, allowing it to be resumed
+        client = SslTest.SslTestConnection( self.client_domain, session_details=initial_session_details )
+
+        #client.transport.trace(Transport.TRACE_DRV)
+        #server.transport.trace(Transport.TRACE_DRV)
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert server.ssl.protocol_name() is not None
+        if(API_LANGUAGE=="C"):
+            assert client.ssl.resume_status() == SSL.RESUME_REUSED
+        else:
+            # Java gives no way to check whether a previous session has been resumed
+            pass
+
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+        # now try to resume using an unknown session-id, expect resume to fail
+        # and a new session is negotiated
+
+        del client
+        del server
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain, session_details=SSLSessionDetails("some-other-session-id") )
+
+        client.connection.open()
+        server.connection.open()
+        self._pump( client, server )
+        assert server.ssl.protocol_name() is not None
+        if(API_LANGUAGE=="C"):
+            assert client.ssl.resume_status() == SSL.RESUME_NEW
+
+        client.connection.close()
+        server.connection.close()
+        self._pump( client, server )
+
+    def test_multiple_sessions(self):
+        """ Test multiple simultaneous active SSL sessions with bi-directional
+        certificate verification, shared across two domains.
+        """
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
+                                                    self._testpath("ca-certificate.pem") )
+
+        self.client_domain.set_credentials(self._testpath("client-certificate.pem"),
+                                           self._testpath("client-private-key.pem"),
+                                           "client-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
+
+        max_count = 100
+        sessions = [(SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ),
+                     SslTest.SslTestConnection( self.client_domain )) for x in
+                    range(max_count)]
+        for s in sessions:
+            s[0].connection.open()
+            self._pump( s[0], s[1] )
+
+        for s in sessions:
+            s[1].connection.open()
+            self._pump( s[1], s[0] )
+            assert s[0].ssl.cipher_name() is not None
+            assert s[1].ssl.cipher_name() == s[0].ssl.cipher_name()
+
+        for s in sessions:
+            s[1].connection.close()
+            self._pump( s[0], s[1] )
+
+        for s in sessions:
+            s[0].connection.close()
+            self._pump( s[1], s[0] )
+
+    def test_server_hostname_authentication(self):
+        """ Test authentication of the names held in the server's certificate
+        against various configured hostnames.
+        """
+        if os.name=="nt":
+            raise Skipped("PROTON-1057: disable temporarily on Windows.")
+
+        # Check the CommonName matches (case insensitive).
+        # Assumes certificate contains "CN=A1.Good.Server.domain.com"
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.ssl.peer_hostname = "a1.good.server.domain.com"
+        assert client.ssl.peer_hostname == "a1.good.server.domain.com"
+        self._do_handshake( client, server )
+        del server
+        del client
+        self.tearDown()
+
+        # Should fail on CN name mismatch:
+        self.setUp()
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                           self._testpath("server-private-key.pem"),
+                                           "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.ssl.peer_hostname = "A1.Good.Server.domain.comX"
+        self._do_handshake( client, server )
+        assert client.transport.closed
+        assert server.transport.closed
+        assert client.connection.state & Endpoint.REMOTE_UNINIT
+        assert server.connection.state & Endpoint.REMOTE_UNINIT
+        del server
+        del client
+        self.tearDown()
+
+        # Wildcarded Certificate
+        # Assumes:
+        #   1) certificate contains Server Alternate Names:
+        #        "alternate.name.one.com" and "another.name.com"
+        #   2) certificate has wildcarded CommonName "*.prefix*.domain.com"
+        #
+
+        # Pass: match an alternate
+        self.setUp()
+        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
+                                           self._testpath("server-wc-private-key.pem"),
+                                           "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.ssl.peer_hostname = "alternate.Name.one.com"
+        self._do_handshake( client, server )
+        del client
+        del server
+        self.tearDown()
+
+        # Pass: match an alternate
+        self.setUp()
+        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
+                                    self._testpath("server-wc-private-key.pem"),
+                                    "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.ssl.peer_hostname = "ANOTHER.NAME.COM"
+        self._do_handshake(client, server)
+        del client
+        del server
+        self.tearDown()
+
+        # Pass: match the pattern
+        self.setUp()
+        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
+                                    self._testpath("server-wc-private-key.pem"),
+                                    "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.ssl.peer_hostname = "SOME.PREfix.domain.COM"
+        self._do_handshake( client, server )
+        del client
+        del server
+        self.tearDown()
+
+        # Pass: match the pattern
+        self.setUp()
+        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
+                                    self._testpath("server-wc-private-key.pem"),
+                                    "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.ssl.peer_hostname = "FOO.PREfixZZZ.domain.com"
+        self._do_handshake( client, server )
+        del client
+        del server
+        self.tearDown()
+
+        # Fail: must match prefix on wildcard
+        self.setUp()
+        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
+                                    self._testpath("server-wc-private-key.pem"),
+                                    "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.ssl.peer_hostname = "FOO.PREfi.domain.com"
+        self._do_handshake( client, server )
+        assert client.transport.closed
+        assert server.transport.closed
+        assert client.connection.state & Endpoint.REMOTE_UNINIT
+        assert server.connection.state & Endpoint.REMOTE_UNINIT
+        del server
+        del client
+        self.tearDown()
+
+        # Fail: leading wildcards are not optional
+        self.setUp()
+        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
+                                    self._testpath("server-wc-private-key.pem"),
+                                    "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        client.ssl.peer_hostname = "PREfix.domain.COM"
+        self._do_handshake( client, server )
+        assert client.transport.closed
+        assert server.transport.closed
+        assert client.connection.state & Endpoint.REMOTE_UNINIT
+        assert server.connection.state & Endpoint.REMOTE_UNINIT
+        self.tearDown()
+
+        # Pass: ensure that the user can give an alternate name that overrides
+        # the connection's configured hostname
+        self.setUp()
+        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
+                                    self._testpath("server-wc-private-key.pem"),
+                                    "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection(self.server_domain, mode=Transport.SERVER)
+        client = SslTest.SslTestConnection(self.client_domain,
+                                           conn_hostname="This.Name.Does.not.Match",
+                                           ssl_peername="alternate.name.one.com")
+        self._do_handshake(client, server)
+        del client
+        del server
+        self.tearDown()
+
+        # Pass: ensure that the hostname supplied by the connection is used if
+        # none has been specified for the SSL instance
+        self.setUp()
+        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
+                                    self._testpath("server-private-key.pem"),
+                                    "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection(self.server_domain, mode=Transport.SERVER)
+        client = SslTest.SslTestConnection(self.client_domain,
+                                           conn_hostname="a1.good.server.domain.com")
+        self._do_handshake(client, server)
+        del client
+        del server
+        self.tearDown()
+
+    def test_server_hostname_authentication_2(self):
+        """Initially separated from test_server_hostname_authentication
+        above to force Windows checking and sidestep PROTON-1057 exclusion.
+        """
+
+        # Fail for a null peer name.
+        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
+                                    self._testpath("server-wc-private-key.pem"),
+                                    "server-password")
+        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
+
+        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
+        client = SslTest.SslTestConnection( self.client_domain )
+
+        # Next line results in an eventual pn_ssl_set_peer_hostname(client.ssl._ssl, None)
+        client.ssl.peer_hostname = None
+        self._do_handshake( client, server )
+        assert client.transport.closed
+        assert server.transport.closed
+        assert client.connection.state & Endpoint.REMOTE_UNINIT
+        assert server.connection.state & Endpoint.REMOTE_UNINIT
+        self.tearDown()
+
+    def test_defaults_messenger_app(self):
+        """ Test an SSL connection using the Messenger apps (no certificates)
+        """
+        if os.name=="nt":
+            raise Skipped("Windows SChannel lacks anonymous cipher support.")
+        port = common.free_tcp_ports()[0]
+
+        receiver = common.MessengerReceiverC()
+        receiver.subscriptions = ["amqps://~0.0.0.0:%s" % port]
+        receiver.receive_count = 1
+        receiver.timeout = self.timeout
+        receiver.start()
+
+        sender = common.MessengerSenderC()
+        sender.targets = ["amqps://0.0.0.0:%s/X" % port]
+        sender.send_count = 1
+        sender.timeout = self.timeout
+        sender.start()
+        sender.wait()
+        assert sender.status() == 0, "Command '%s' failed" % str(sender.cmdline())
+
+        receiver.wait()
+        assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline())
+
+    def test_server_authentication_messenger_app(self):
+        """ Test an SSL authentication using the Messenger apps.
+        """
+        port = common.free_tcp_ports()[0]
+
+        receiver = common.MessengerReceiverC()
+        receiver.subscriptions = ["amqps://~0.0.0.0:%s" % port]
+        receiver.receive_count = 1
+        receiver.timeout = self.timeout
+        # Note hack - by default we use the client-certificate for the
+        # _server_ because the client-certificate's common name field
+        # is "127.0.0.1", which will match the target address used by
+        # the sender.
+        receiver.certificate = self._testpath("client-certificate.pem")
+        receiver.privatekey = self._testpath("client-private-key.pem")
+        receiver.password = "client-password"
+        receiver.start()
+
+        sender = common.MessengerSenderC()
+        sender.targets = ["amqps://127.0.0.1:%s/X" % port]
+        sender.send_count = 1
+        sender.timeout = self.timeout
+        sender.ca_db = self._testpath("ca-certificate.pem")
+        sender.start()
+        sender.wait()
+        assert sender.status() == 0, "Command '%s' failed" % str(sender.cmdline())
+
+        receiver.wait()
+        assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline())
+
+    def DISABLED_test_defaults_valgrind(self):
+        """ Run valgrind over a simple SSL connection (no certificates)
+        """
+        # the openssl libraries produce far too many valgrind errors to be
+        # useful.  AFAIK, there is no way to wriate a valgrind suppression
+        # expression that will ignore all errors from a given library.
+        # Until we can, skip this test.
+        port = common.free_tcp_ports()[0]
+
+        receiver = common.MessengerReceiverValgrind()
+        receiver.subscriptions = ["amqps://~127.0.0.1:%s" % port]
+        receiver.receive_count = 1
+        receiver.timeout = self.timeout
+        receiver.start()
+
+        sender = common.MessengerSenderValgrind()
+        sender.targets = ["amqps://127.0.0.1:%s/X" % port]
+        sender.send_count = 1
+        sender.timeout = self.timeout
+        sender.start()
+        sender.wait()
+        assert sender.status() == 0, "Command '%s' failed" % str(sender.cmdline())
+
+        receiver.wait()
+        assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline())
+
+        # self.server_domain.set_credentials(self._testpath("client-certificate.pem"),
+        #                                    self._testpath("client-private-key.pem"),
+        #                                    "client-password")
+
+        # self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
+        # self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
+
+    def test_singleton(self):
+        """Verify that only a single instance of SSL can exist per Transport"""
+        transport = Transport()
+        ssl1 = SSL(transport, self.client_domain)
+        ssl2 = transport.ssl(self.client_domain)
+        ssl3 = transport.ssl(self.client_domain)
+        assert ssl1 is ssl2
+        assert ssl1 is ssl3
+        transport = Transport()
+        ssl1 = transport.ssl(self.client_domain)
+        ssl2 = SSL(transport, self.client_domain)
+        assert ssl1 is ssl2
+        # catch attempt to re-configure existing SSL
+        try:
+            ssl3 = SSL(transport, self.server_domain)
+            assert False, "Expected error did not occur!"
+        except SSLException:
+            pass

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/README.txt
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/README.txt b/python/tests/proton_tests/ssl_db/README.txt
new file mode 100644
index 0000000..20c92b2
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/README.txt
@@ -0,0 +1,79 @@
+The following certificate files are used by the SSL unit tests (ssl.py):
+
+ca-certificate.pem - contains the public certificate identifying a "trusted" Certificate
+Authority.  This certificate is used to sign the certificates that identify the SSL
+servers and clients run by the tests.
+
+client-certificate.pem - the public certificate used to identify the client.  Signed by
+the CA.
+
+client-private-key.pem - encrypted key used to create client-certificate.pem.  Password is
+"client-password"
+
+server-certificate.pem - the public certificate used to identify the server.  Signed by
+the CA.  The CommonName is "A1.Good.Server.domain.com", and is checked by some unit tests.
+
+server-private-key.pem - encrypted key used to create server-certificate.pem. Password is
+"server-password"
+
+bad-server-certificate.pem, bad-server-private-key.pem - a certificate/key that is not trusted by the client, for negative test.
+
+server-wc-certificate.pem and server-wc-private-key.pem - similar to
+server-certificate.pem and server-private-key.pem, but contains Subject Alternate Name
+entries, and a wildcard CommonName.  Used for certificate name checking tests.
+
+These certificates have been created using the OpenSSL tool.
+
+The following bash script can be used to create these certificates (requires keytool from Java 1.7, and openssl):
+
+--8<--
+#!/bin/bash
+#set -x
+
+rm -f *.pem *.pkcs12
+
+# Create a self-signed certificate for the CA, and a private key to sign certificate requests:
+keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -genkey -dname "O=Trust Me Inc.,CN=Trusted.CA.com" -validity 99999 -ext bc:c=ca:true,pathlen:0 -ext ku:c=digitalSignature,keyCertSign -ext ExtendedkeyUsage=serverAuth,clientAuth
+openssl pkcs12 -nokeys -passin pass:ca-password -in ca.pkcs12 -passout pass:ca-password -out ca-certificate.pem
+
+# Create a certificate request for the server certificate.  Use the CA's certificate to sign it:
+keytool -storetype pkcs12 -keystore server.pkcs12 -storepass server-password -alias server-certificate -keypass server-password -genkey  -dname "O=Server,CN=A1.Good.Server.domain.com" -validity 99999
+keytool -storetype pkcs12 -keystore server.pkcs12 -storepass server-password -alias server-certificate -keypass server-password -certreq -file server-request.pem
+keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile server-request.pem -outfile server-certificate.pem
+openssl pkcs12 -nocerts -passin pass:server-password -in server.pkcs12 -passout pass:server-password -out server-private-key.pem
+
+# Create a certificate request for the client certificate.  Use the CA's certificate to sign it:
+keytool -storetype pkcs12 -keystore client.pkcs12 -storepass client-password -alias client-certificate -keypass client-password -genkey  -dname "O=Client,CN=127.0.0.1" -validity 99999
+keytool -storetype pkcs12 -keystore client.pkcs12 -storepass client-password -alias client-certificate -keypass client-password -certreq -file client-request.pem
+keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile client-request.pem -outfile client-certificate.pem
+openssl pkcs12 -nocerts -passin pass:client-password -in client.pkcs12 -passout pass:client-password -out client-private-key.pem
+
+# Create another client certificate with a different subject line
+keytool -storetype pkcs12 -keystore client1.pkcs12 -storepass client-password -alias client-certificate1 -keypass client-password -genkey  -dname "O=Client,CN=127.0.0.1,C=US,ST=ST,L=City,OU=Dev" -validity 99999
+keytool -storetype pkcs12 -keystore client1.pkcs12 -storepass client-password -alias client-certificate1 -keypass client-password -certreq -file client-request1.pem
+keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile client-request1.pem -outfile client-certificate1.pem
+openssl pkcs12 -nocerts -passin pass:client-password -in client1.pkcs12 -passout pass:client-password -out client-private-key1.pem
+
+# Create a "bad" certificate - not signed by a trusted authority
+keytool -storetype pkcs12 -keystore bad-server.pkcs12 -storepass server-password -alias bad-server -keypass server-password -genkey -dname "O=Not Trusted Inc,CN=127.0.0.1" -validity 99999
+openssl pkcs12 -nocerts -passin pass:server-password -in bad-server.pkcs12 -passout pass:server-password -out bad-server-private-key.pem
+openssl pkcs12 -nokeys  -passin pass:server-password -in bad-server.pkcs12 -passout pass:server-password -out bad-server-certificate.pem
+
+# Create a server certificate with several alternate names, including a wildcarded common name:
+keytool -ext san=dns:alternate.name.one.com,dns:another.name.com -storetype pkcs12 -keystore server-wc.pkcs12 -storepass server-password -alias server-wc-certificate -keypass server-password -genkeypair -dname "O=Server,CN=*.prefix*.domain.com" -validity 99999
+keytool -ext san=dns:alternate.name.one.com,dns:another.name.com -storetype pkcs12 -keystore server-wc.pkcs12 -storepass server-password -alias server-wc-certificate -keypass server-password -certreq -file server-wc-request.pem
+keytool -ext san=dns:alternate.name.one.com,dns:another.name.com  -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile server-wc-request.pem -outfile server-wc-certificate.pem
+openssl pkcs12 -nocerts -passin pass:server-password -in server-wc.pkcs12 -passout pass:server-password -out server-wc-private-key.pem
+
+# Create pkcs12 versions of the above certificates (for Windows SChannel)
+# The CA certificate store/DB is created without public keys.
+# Give the "p12" files the same base name so the tests can just change the extension to switch between platforms.
+# These certificates might work for OpenSSL <-> SChannel interop tests, but note that the DH cypher suite
+# overlap is poor between platforms especially for older Windows versions.  RSA certificates are better for
+# interop (or PFS-friendly certificates on newer platforms).
+openssl pkcs12 -export -out ca-certificate.p12 -in ca-certificate.pem -name ca-certificate -nokeys -passout pass:
+openssl pkcs12 -export -out server-certificate.p12 -passin pass:server-password -passout pass:server-password -inkey server-private-key.pem -in server-certificate.pem -name server-certificate
+openssl pkcs12 -export -out client-certificate.p12 -passin pass:client-password -passout pass:client-password -inkey client-private-key.pem -in client-certificate.pem -name client-certificate
+openssl pkcs12 -export -out client-certificate1.p12 -passin pass:client-password -passout pass:client-password -inkey client-private-key1.pem -in client-certificate1.pem -name client-certificate1
+openssl pkcs12 -export -out bad-server-certificate.p12 -passin pass:server-password -passout pass:server-password -inkey bad-server-private-key.pem -in bad-server-certificate.pem -name bad-server
+openssl pkcs12 -export -out server-wc-certificate.p12 -passin pass:server-password -passout pass:server-password -inkey server-wc-private-key.pem -in server-wc-certificate.pem -name server-wc-certificate

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/bad-server-certificate.p12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/bad-server-certificate.p12 b/python/tests/proton_tests/ssl_db/bad-server-certificate.p12
new file mode 100644
index 0000000..7906831
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/bad-server-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/bad-server-certificate.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/bad-server-certificate.pem b/python/tests/proton_tests/ssl_db/bad-server-certificate.pem
new file mode 100644
index 0000000..1dc288b
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/bad-server-certificate.pem
@@ -0,0 +1,22 @@
+Bag Attributes
+    friendlyName: bad-server
+    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 38 32 39 36
+subject=/CN=127.0.0.1/O=Not Trusted Inc
+issuer=/CN=127.0.0.1/O=Not Trusted Inc
+-----BEGIN CERTIFICATE-----
+MIICuzCCAnmgAwIBAgIELMpW4jALBgcqhkjOOAQDBQAwLjESMBAGA1UEAxMJMTI3
+LjAuMC4xMRgwFgYDVQQKEw9Ob3QgVHJ1c3RlZCBJbmMwIBcNMTcwODAyMjE1MzM4
+WhgPMjI5MTA1MTcyMTUzMzhaMC4xEjAQBgNVBAMTCTEyNy4wLjAuMTEYMBYGA1UE
+ChMPTm90IFRydXN0ZWQgSW5jMIIBuDCCASwGByqGSM44BAEwggEfAoGBAP1/U4Ed
+dRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs
+14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208Ue
+wwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BY
+HPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+Zx
+BxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx
++2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYUAAoGBAK3E
+5j/UaiVHJYAf3DAIl5hjTZcChTp57GjODdfDteHeDh85HFyW0kxmXyhpUdODzAgG
+THhpxy/+Kkd8jmUBVFnU1EXByvGORBfnJkMTkuhmk9veytxlskQ0tQV8gmRNb0Xe
+hie7T9UT8TQJy9mPS74pSuviFSx0Hz0dKGi0eVUYoyEwHzAdBgNVHQ4EFgQUg2PE
+qycdV1oxVaA33ULDrVdSjhkwCwYHKoZIzjgEAwUAAy8AMCwCFGybqSwG3TauRJVw
+XA/xeSxpYbcBAhQ6ylf9XZAvM7tMyQQTcDAkmt+YWQ==
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/bad-server-private-key.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/bad-server-private-key.pem b/python/tests/proton_tests/ssl_db/bad-server-private-key.pem
new file mode 100644
index 0000000..331ade0
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/bad-server-private-key.pem
@@ -0,0 +1,15 @@
+Bag Attributes
+    friendlyName: bad-server
+    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 38 32 39 36
+Key Attributes: <No Attributes>
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIqgLLe7iT+1wCAggA
+MBQGCCqGSIb3DQMHBAhg98ZJQMtngwSCAVCdhdOMr+VVTNaIPSy4nSwdRTlXIuRa
+4wPi+07mToJmEtGfpJ4MPjDF9yRptVQI4RoN/RrLl0WX/HNZ5U4JluL0j68+JB1d
+MoeSRiRc+Yd2vxey8reBrvx1m1mB3LXvm38oZVDFrQ9FNGK09EtTLN1rqckr1fxQ
+Imcvb63nu5UZB8WMCVfKqe9Zm9dQlsSlp3M5OCRm296Xsr0eWwe2W1/rJiKMZN7x
+eJMf4pWVrBHoi6VJHAEA7ZvhRfcHkSbyze5ouDpKbMZS9gq38Hs4d+wkxe9x3emx
+6OvppcpBolZhntF1vJXUXMc6D5Pw3mGEsRGwcMJqWCc8XJTkyP0ylNFNyaHaz0oC
+jSWmUu0s5628K+m8nGY4X7msfOddTA16W6mODjE2ddlTqwTFu2CYBk3WbprBRXo0
+ionZQTPTqcM0UR3KyF9CHRZbnQ/d7bk57/w=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/bad-server.pkcs12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/bad-server.pkcs12 b/python/tests/proton_tests/ssl_db/bad-server.pkcs12
new file mode 100644
index 0000000..dea2143
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/bad-server.pkcs12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/ca-certificate.p12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/ca-certificate.p12 b/python/tests/proton_tests/ssl_db/ca-certificate.p12
new file mode 100644
index 0000000..767b24d
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/ca-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/ca-certificate.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/ca-certificate.pem b/python/tests/proton_tests/ssl_db/ca-certificate.pem
new file mode 100644
index 0000000..6d27395
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/ca-certificate.pem
@@ -0,0 +1,24 @@
+Bag Attributes
+    friendlyName: ca
+    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 36 34 37 32
+subject=/CN=Trusted.CA.com/O=Trust Me Inc.
+issuer=/CN=Trusted.CA.com/O=Trust Me Inc.
+-----BEGIN CERTIFICATE-----
+MIIDBDCCAsKgAwIBAgIEBGGY1zALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1
+c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTcwODAyMjE1
+MzM2WhgPMjI5MTA1MTcyMTUzMzZaMDExFzAVBgNVBAMTDlRydXN0ZWQuQ0EuY29t
+MRYwFAYDVQQKEw1UcnVzdCBNZSBJbmMuMIIBuDCCASwGByqGSM44BAEwggEfAoGB
+AP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6
+MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E
++4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC
+ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeO
+utRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/
+C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYUA
+AoGBALsRT+tH1c+TC78EYtPh+KQ0DosKKtxeSRos4eQ49erdI+tYhzeqN3Ebmeky
+TWfGjjU64PGRFDNGjpf9l7Yo22jk9U5zIFkFp5gP9DVBHrOrh8mdT+/oBhhVHxI5
+rWLqSjI/zXhRzRwueR81p0D3XJlV3g/xlOlWALoRnUWpDAo3o2QwYjASBgNVHRMB
+Af8ECDAGAQH/AgEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV
+HQ8BAf8EBAMCAoQwHQYDVR0OBBYEFLI2ezwilYHGS5MRPMWlifHH+Y5qMAsGByqG
+SM44BAMFAAMvADAsAhRxomjEvDfhe1p+D6KLc0IGjDNgtgIUIZXb0/Fpzy6dpCwe
+Ay+soxvpfMU=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/ca.pkcs12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/ca.pkcs12 b/python/tests/proton_tests/ssl_db/ca.pkcs12
new file mode 100644
index 0000000..d9ca00c
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/ca.pkcs12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/client-certificate.p12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/client-certificate.p12 b/python/tests/proton_tests/ssl_db/client-certificate.p12
new file mode 100644
index 0000000..82271f9
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/client-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/client-certificate.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/client-certificate.pem b/python/tests/proton_tests/ssl_db/client-certificate.pem
new file mode 100644
index 0000000..4c0d4d4
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/client-certificate.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC1jCCApOgAwIBAgIEeg2f8DALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1
+c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTcwODAyMjE1
+MzM3WhgPMjI5MTA1MTcyMTUzMzdaMCUxEjAQBgNVBAMTCTEyNy4wLjAuMTEPMA0G
+A1UEChMGQ2xpZW50MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9K
+nC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00
+b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNa
+FpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA
+9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ
+FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7
+zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAJ3g1ohpHgoxH
+3Yj0SIfiPcUaM5FIszemFwQ2FZoG/J7MiVIw442JheTR/iEB3LYheHBp7ToqhaMY
+NYidcxxUzgZJs3worXqAuUgDdbDcW6AjQ4olyGVt7sX9OL2amMq9BFCIt7SlyDKW
+8Accx46H+8BffMdCu56yw5WQtZ3cPD2jQjBAMB8GA1UdIwQYMBaAFLI2ezwilYHG
+S5MRPMWlifHH+Y5qMB0GA1UdDgQWBBQg7FbClmtrSAHA9lR8E7uexl5p1jALBgcq
+hkjOOAQDBQADMAAwLQIVAIpUbUYyA3DisZyENQwcN0rDQ+FyAhRPcfg9Slb6MfO4
+SBFqOiesk+cpqw==
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/client-certificate1.p12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/client-certificate1.p12 b/python/tests/proton_tests/ssl_db/client-certificate1.p12
new file mode 100644
index 0000000..d35f88f
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/client-certificate1.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/client-certificate1.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/client-certificate1.pem b/python/tests/proton_tests/ssl_db/client-certificate1.pem
new file mode 100644
index 0000000..c63b4f1
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/client-certificate1.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDDCCAsqgAwIBAgIEBmzTzzALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1
+c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTcwODAyMjE1
+MzM4WhgPMjI5MTA1MTcyMTUzMzhaMFwxDDAKBgNVBAsTA0RldjENMAsGA1UEBxME
+Q2l0eTELMAkGA1UECBMCU1QxCzAJBgNVBAYTAlVTMRIwEAYDVQQDEwkxMjcuMC4w
+LjExDzANBgNVBAoTBkNsaWVudDCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OB
+HXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tV
+bNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPF
+HsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvw
+WBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/m
+cQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi
+8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GEAAKBgHVu
+urVq1FFws/JN+I3yfA2RVmFwlYJID8yyO9lkHBPBDE0dqfFBF6F3nwsCiZF0n/v4
+od6MuuRSplV4kZH0jOOVw7e9cF2RNd/KahsIpm/Oq5aosm6W7KDK/xIwNyW+3DFt
+TGDTOZ6ejVMgGR2rAD+FEp2yycJACQBP1GtTSFXTo0IwQDAfBgNVHSMEGDAWgBSy
+Nns8IpWBxkuTETzFpYnxx/mOajAdBgNVHQ4EFgQUz4cx+zNqsCmWpBU2dw8GHO33
++eEwCwYHKoZIzjgEAwUAAy8AMCwCFCsfHJPB4Tq6qX5U+DZBc3jmLBiXAhRF17Dz
+fq+AxqyQ9PvTtH3UbFh1hQ==
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/client-private-key.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/client-private-key.pem b/python/tests/proton_tests/ssl_db/client-private-key.pem
new file mode 100644
index 0000000..bca85eb
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/client-private-key.pem
@@ -0,0 +1,15 @@
+Bag Attributes
+    friendlyName: client-certificate
+    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 37 32 33 39
+Key Attributes: <No Attributes>
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIHmVKa1dEtm4CAggA
+MBQGCCqGSIb3DQMHBAgpc0Ay33xL9ASCAVBJ8D5DVRd0d6t3gSvTFBAflpUROv2/
+pQlMLGbGlJIoEPyMIc9/GcgS7U19nMdoJjI1TuT/hGwObualnRRjY6KL5cbK2oUQ
+371yUs6jGIQxtCeb1WgKpA/FKw9jRO7Tg5ztObItPiSQvkOcssfdRJYI1+W+ovj+
+j1BKMkJu197twIChYaz+3ppJzrh3qlqFgdRdE9H04ffWpNaZ6aOIIJHPMuZ8FScu
+bQyvD9JjI+JWJUaCyp/3dxxxVrZ3vu8i6LmrL6Nm9IkJtFMZOfgPkoRLML2DWKqB
+1qLk/Z45/THXDAxrPggFfqMvuctwJmtAGvo3MIbfCi+aewJE6/DjlSHDv6wGvOGB
+T5golvZ5siahHqwmufSQG8ZTsGcpu/jCA5ipIvcTVgWIxscNc2Yx9FDNWVNzUcTy
+ctRX6DS+s7rAy9ISjch4BbAtI7yALFt63eU=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/client-private-key1.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/client-private-key1.pem b/python/tests/proton_tests/ssl_db/client-private-key1.pem
new file mode 100644
index 0000000..bedf540
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/client-private-key1.pem
@@ -0,0 +1,15 @@
+Bag Attributes
+    friendlyName: client-certificate1
+    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 37 37 37 32
+Key Attributes: <No Attributes>
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIg1n9vdGttqoCAggA
+MBQGCCqGSIb3DQMHBAgRjlrRQfGcLQSCAVChui/M+36/e0WzeM79aJV7YZds/OJY
+gprtJ2g5Cxb1L9hymwgxJtOAaRUqLUcfLHcKSxA+MaB+Ij+/8TH+miq0zZ9q0jZV
+BAm56FNgUjW0nPLueTNhWzVVfQU6H9Tj33OuKm1PQo84Af3OPMtE03pvGDPEAPbH
+a72HUgZyI7WTux4wpxfvUEVkT5OXgBHrFlqXiHHCI+9kqBXMCV3oHgZBcO+dqPKS
+rlaTY7xoQWLenB6EQeYopMA2GNUVtzB3y6/nX2z0Yp5oHqKPBNOyFlVmwCrENN1/
+qnrFfzVbnksWLKhg9O+TPsId1UIZVvBh67y5N5IZRrpuE03qd2BScKM/Tn6vkWNB
+Eus74Vba5vw9prauRC45FVgDe2YYYoULYPfhXWSiiWHDNKOBlz3l3hGlZsC8wKe5
+QlV5bVcOTfGIaBkD7SQyfRjMr8SWj4WMw1M=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/client-request.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/client-request.pem b/python/tests/proton_tests/ssl_db/client-request.pem
new file mode 100644
index 0000000..b247aab
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/client-request.pem
@@ -0,0 +1,15 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIICWTCCAhcCAQAwJTESMBAGA1UEAxMJMTI3LjAuMC4xMQ8wDQYDVQQKEwZDbGll
+bnQwggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I8
+70QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWk
+n5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HX
+Ku/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8
+q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fP
+CTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD
+3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhAACgYAneDWiGkeCjEfdiPRIh+I9xRoz
+kUizN6YXBDYVmgb8nsyJUjDjjYmF5NH+IQHctiF4cGntOiqFoxg1iJ1zHFTOBkmz
+fCiteoC5SAN1sNxboCNDiiXIZW3uxf04vZqYyr0EUIi3tKXIMpbwBxzHjof7wF98
+x0K7nrLDlZC1ndw8PaAwMC4GCSqGSIb3DQEJDjEhMB8wHQYDVR0OBBYEFCDsVsKW
+a2tIAcD2VHwTu57GXmnWMAsGByqGSM44BAMFAAMvADAsAhQY5Zy4fQcy/SZOJ2Ix
+cl3/QfimvQIUVvSdet7NKWzMQoBDhlJTdTzJvE8=
+-----END NEW CERTIFICATE REQUEST-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/client-request1.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/client-request1.pem b/python/tests/proton_tests/ssl_db/client-request1.pem
new file mode 100644
index 0000000..b46eb0a
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/client-request1.pem
@@ -0,0 +1,16 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIICkTCCAk4CAQAwXDEMMAoGA1UECxMDRGV2MQ0wCwYDVQQHEwRDaXR5MQswCQYD
+VQQIEwJTVDELMAkGA1UEBhMCVVMxEjAQBgNVBAMTCTEyNy4wLjAuMTEPMA0GA1UE
+ChMGQ2xpZW50MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s
+5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/Jm
+YLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy
+9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+Gg
+hdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj
+6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTx
+vqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAdW66tWrUUXCz8k34
+jfJ8DZFWYXCVgkgPzLI72WQcE8EMTR2p8UEXoXefCwKJkXSf+/ih3oy65FKmVXiR
+kfSM45XDt71wXZE138pqGwimb86rlqiybpbsoMr/EjA3Jb7cMW1MYNM5np6NUyAZ
+HasAP4USnbLJwkAJAE/Ua1NIVdOgMDAuBgkqhkiG9w0BCQ4xITAfMB0GA1UdDgQW
+BBTPhzH7M2qwKZakFTZ3DwYc7ff54TALBgcqhkjOOAQDBQADMAAwLQIUFs17HaTm
+vest72/4Caoo1sH39n0CFQCR680PPwr3lZ5jjEOp+n4htQNUvw==
+-----END NEW CERTIFICATE REQUEST-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/client.pkcs12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/client.pkcs12 b/python/tests/proton_tests/ssl_db/client.pkcs12
new file mode 100644
index 0000000..575a551
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/client.pkcs12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/client1.pkcs12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/client1.pkcs12 b/python/tests/proton_tests/ssl_db/client1.pkcs12
new file mode 100644
index 0000000..0e7c888
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/client1.pkcs12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/server-certificate.p12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/server-certificate.p12 b/python/tests/proton_tests/ssl_db/server-certificate.p12
new file mode 100644
index 0000000..cacfa89
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/server-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/server-certificate.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/server-certificate.pem b/python/tests/proton_tests/ssl_db/server-certificate.pem
new file mode 100644
index 0000000..462f3a5
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/server-certificate.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC5jCCAqSgAwIBAgIEX8z6MDALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1
+c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTcwODAyMjE1
+MzM3WhgPMjI5MTA1MTcyMTUzMzdaMDUxIjAgBgNVBAMTGUExLkdvb2QuU2VydmVy
+LmRvbWFpbi5jb20xDzANBgNVBAoTBlNlcnZlcjCCAbgwggEsBgcqhkjOOAQBMIIB
+HwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6
+v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58ao
+phUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvM
+spK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4Jn
+UVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1
+kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kq
+A4GFAAKBgQCERpy6RrkNHpgXT/uL9gN/IgwY7kp3Iwzr1lrqo+HqmydE+Cz9uqPH
+VyxjX7nHVrdwl7xgsoki3QyoKcrZfTL1oS79kodWG7t6CyOtj2L3KGMUdIlqWepZ
+wzCKTWrb07VjpqhMh0Qh8+IqEmvfC/4UVOec9alX0NO/ckDbIBhITqNCMEAwHwYD
+VR0jBBgwFoAUsjZ7PCKVgcZLkxE8xaWJ8cf5jmowHQYDVR0OBBYEFBhEDdcBRqn5
+wFEbAad559yrQPE7MAsGByqGSM44BAMFAAMvADAsAhRuMRxWMKxy3USjfSFn47H4
+Z5VIHgIUB2i6+RQi7dHOEQYKKmxdQvAPA9M=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/server-private-key.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/server-private-key.pem b/python/tests/proton_tests/ssl_db/server-private-key.pem
new file mode 100644
index 0000000..3ae25f8
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/server-private-key.pem
@@ -0,0 +1,15 @@
+Bag Attributes
+    friendlyName: server-certificate
+    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 36 36 35 36
+Key Attributes: <No Attributes>
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI6jwDH/9bZYMCAggA
+MBQGCCqGSIb3DQMHBAgbIQ8UrRfmAgSCAVDejPh9sT2PMvDjjzXG6xpSmBPNZRiz
+f2k2a9EaI8L4xadveiZTzOpk2C/nltMCNY2Vwf/LMtbvcLiadBRWM/4Uf5fvL/94
+zlKE77wPSWK1R+btZm0KIaA+EPAvnIGcjHlcSU58eQexwVlMXJ9pdeHm9KWbV1D+
+PjrlJ+SDq7OSGprTCz9r+gQ7Fy2Oe9OKc92tE29QD2AZXtSodvY9CosXCx4cqXr3
+ey+HXmVXJohsL89NycL80TvkxppqZ1hT3DZMkrFg2jFPz505rzE48y62FMoKNCjQ
+6HXvsniWYXf7ipr+A4/diSSMBr/zmA+H+ZHKlNO8FJqZ8eI1eqRO+PjO1VV9bbG0
+lYoeoFu0Y1xw6V2jLYnFF1mTCC6kegl6kruvnwO7Oy+6kPEvDrejuI6uozW2etej
+cBq1lUK5QNKSoaB7Qw+2qlyFg/KFwXXDBqk=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/server-request.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/server-request.pem b/python/tests/proton_tests/ssl_db/server-request.pem
new file mode 100644
index 0000000..bd53fab
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/server-request.pem
@@ -0,0 +1,15 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIICazCCAigCAQAwNTEiMCAGA1UEAxMZQTEuR29vZC5TZXJ2ZXIuZG9tYWluLmNv
+bTEPMA0GA1UEChMGU2VydmVyMIIBuDCCASwGByqGSM44BAEwggEfAoGBAP1/U4Ed
+dRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs
+14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208Ue
+wwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BY
+HPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+Zx
+BxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx
++2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYUAAoGBAIRG
+nLpGuQ0emBdP+4v2A38iDBjuSncjDOvWWuqj4eqbJ0T4LP26o8dXLGNfucdWt3CX
+vGCyiSLdDKgpytl9MvWhLv2Sh1Ybu3oLI62PYvcoYxR0iWpZ6lnDMIpNatvTtWOm
+qEyHRCHz4ioSa98L/hRU55z1qVfQ079yQNsgGEhOoDAwLgYJKoZIhvcNAQkOMSEw
+HzAdBgNVHQ4EFgQUGEQN1wFGqfnAURsBp3nn3KtA8TswCwYHKoZIzjgEAwUAAzAA
+MC0CFFIXSYKFVq90wR3lH+KCwvL+j0A4AhUAlxeczUtqTQFeGXFsDwIGO+5/uA4=
+-----END NEW CERTIFICATE REQUEST-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/server-wc-certificate.p12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/server-wc-certificate.p12 b/python/tests/proton_tests/ssl_db/server-wc-certificate.p12
new file mode 100644
index 0000000..3f8a53d
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/server-wc-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/server-wc-certificate.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/server-wc-certificate.pem b/python/tests/proton_tests/ssl_db/server-wc-certificate.pem
new file mode 100644
index 0000000..4d32b40
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/server-wc-certificate.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDFTCCAtOgAwIBAgIEVTK/cTALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1
+c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTcwODAyMjE1
+MzM4WhgPMjI5MTA1MTcyMTUzMzhaMDAxHTAbBgNVBAMMFCoucHJlZml4Ki5kb21h
+aW4uY29tMQ8wDQYDVQQKEwZTZXJ2ZXIwggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA
+/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow
+9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7
+g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi
+64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV466
+1FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L
++iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhAAC
+gYATsU4dSb5vvYkuhnLJPYpiHOEOagLSwwggm8CD4JqA8CC/lzIJBI3LkR7Ve1Mw
+xYiDbQQPaxGsdCxaDuE+rOHmJcCNxum4gIYxeOOGHLa9eezTXLu2s0kBgsWx3I0U
+98lI4E+gRHiU27NXlNiEKvVq3GhzWvKdUqClbtLZ+67gzqN3MHUwHwYDVR0jBBgw
+FoAUsjZ7PCKVgcZLkxE8xaWJ8cf5jmowMwYDVR0RBCwwKoIWYWx0ZXJuYXRlLm5h
+bWUub25lLmNvbYIQYW5vdGhlci5uYW1lLmNvbTAdBgNVHQ4EFgQUas7dEjv/R3ig
+GcCdPRLL5P3HPU8wCwYHKoZIzjgEAwUAAy8AMCwCFFuvuEosI+5a+lSmpEahvhyE
+31WUAhR6+NkSdChlT0v6HmjyhBL1hLZYNA==
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/server-wc-private-key.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/server-wc-private-key.pem b/python/tests/proton_tests/ssl_db/server-wc-private-key.pem
new file mode 100644
index 0000000..7bae296
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/server-wc-private-key.pem
@@ -0,0 +1,15 @@
+Bag Attributes
+    friendlyName: server-wc-certificate
+    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 38 34 39 33
+Key Attributes: <No Attributes>
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIFt9KwMYb/OQCAggA
+MBQGCCqGSIb3DQMHBAjQ+Hr462sAigSCAVAmqByfn+Ujb9TfpEI0d6mlW7Nyko00
+chzSFz61RVA/twfbLImhYvEo7P+UglcqGc1H3DaysDuMjbiNqgP25lDHO6ndhN7r
+XaeNshI8U3RQfUrhTwcA2pGpHQ6t+TGNKifRuJMbcHxWDNr+Tdod8uUADZt8Ywb+
+WQOqIrByNJryx5i2yZT7FphYrz6N0L5cNKVIirNv9/FOlKiyuzzg5c4NmABkpajE
+ZyT2H1p/qFipz8XeQ7BvFVDWSGn6Jb8vRvcc/swoCNSs8Wukr7tbryie2IbgktES
+gw7mVOw/Wdw6u26Q8Dz1c+eyy1WPuCiubFKUK12Ul0X9KKYCufVvQPoQBsMGikRM
+JcvrMd1cZ60pANJhnrogE6VEYE3NQrPC6SNao0NB+g4CW3tOH6m80H5+yHrMdvjo
+MQNXdlwdNWrCEH6hXJxzuE1qM5Ajc82bfwo=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/server-wc-request.pem
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/server-wc-request.pem b/python/tests/proton_tests/ssl_db/server-wc-request.pem
new file mode 100644
index 0000000..f6f13bd
--- /dev/null
+++ b/python/tests/proton_tests/ssl_db/server-wc-request.pem
@@ -0,0 +1,16 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIICmTCCAlcCAQAwMDEdMBsGA1UEAwwUKi5wcmVmaXgqLmRvbWFpbi5jb20xDzAN
+BgNVBAoTBlNlcnZlcjCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLf
+Spwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4Ad
+NG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQT
+WhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGB
+APfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0
+SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEk
+O8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GEAAKBgBOxTh1Jvm+9
+iS6Gcsk9imIc4Q5qAtLDCCCbwIPgmoDwIL+XMgkEjcuRHtV7UzDFiINtBA9rEax0
+LFoO4T6s4eYlwI3G6biAhjF444Yctr157NNcu7azSQGCxbHcjRT3yUjgT6BEeJTb
+s1eU2IQq9WrcaHNa8p1SoKVu0tn7ruDOoGUwYwYJKoZIhvcNAQkOMVYwVDAzBgNV
+HREELDAqghZhbHRlcm5hdGUubmFtZS5vbmUuY29tghBhbm90aGVyLm5hbWUuY29t
+MB0GA1UdDgQWBBRqzt0SO/9HeKAZwJ09Esvk/cc9TzALBgcqhkjOOAQDBQADLwAw
+LAIUNn3ravBNvEsgZRjQd4EPPvQ1k9wCFEuakAyAzmt2ZfIKX3ZmTIgNKsvy
+-----END NEW CERTIFICATE REQUEST-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/server-wc.pkcs12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/server-wc.pkcs12 b/python/tests/proton_tests/ssl_db/server-wc.pkcs12
new file mode 100644
index 0000000..0ceccbc
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/server-wc.pkcs12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/ssl_db/server.pkcs12
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl_db/server.pkcs12 b/python/tests/proton_tests/ssl_db/server.pkcs12
new file mode 100644
index 0000000..f3c19e2
Binary files /dev/null and b/python/tests/proton_tests/ssl_db/server.pkcs12 differ


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[04/11] qpid-proton git commit: PROTON-1885: [python] move tests/python to python/tests

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl.py b/tests/python/proton_tests/ssl.py
deleted file mode 100644
index d2e2f44..0000000
--- a/tests/python/proton_tests/ssl.py
+++ /dev/null
@@ -1,936 +0,0 @@
-from __future__ import absolute_import
-#
-# 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.
-#
-
-import os
-from . import common
-import random
-import string
-import subprocess
-import sys
-from proton import *
-from .common import Skipped, pump
-
-
-def _testpath(file):
-    """ Set the full path to the certificate,keyfile, etc. for the test.
-    """
-    if os.name=="nt":
-        if file.find("private-key")!=-1:
-            # The private key is not in a separate store
-            return None
-        # Substitute pkcs#12 equivalent for the CA/key store
-        if file.endswith(".pem"):
-            file = file[:-4] + ".p12"
-    return os.path.join(os.path.dirname(__file__),
-                        "ssl_db/%s" % file)
-
-class SslTest(common.Test):
-
-    def __init__(self, *args):
-        common.Test.__init__(self, *args)
-        self._testpath = _testpath
-
-    def setUp(self):
-        if not common.isSSLPresent():
-            raise Skipped("No SSL libraries found.")
-        self.server_domain = SSLDomain(SSLDomain.MODE_SERVER)
-        self.client_domain = SSLDomain(SSLDomain.MODE_CLIENT)
-
-    def tearDown(self):
-        self.server_domain = None
-        self.client_domain = None
-
-    class SslTestConnection(object):
-        """ Represents a single SSL connection.
-        """
-        def __init__(self, domain=None, mode=Transport.CLIENT,
-                     session_details=None, conn_hostname=None,
-                     ssl_peername=None):
-            if not common.isSSLPresent():
-                raise Skipped("No SSL libraries found.")
-
-            self.ssl = None
-            self.domain = domain
-            self.transport = Transport(mode)
-            self.connection = Connection()
-            if conn_hostname:
-                self.connection.hostname = conn_hostname
-            if domain:
-                self.ssl = SSL( self.transport, self.domain, session_details )
-                if ssl_peername:
-                    self.ssl.peer_hostname = ssl_peername
-            # bind last, after all configuration complete:
-            self.transport.bind(self.connection)
-
-    def _pump(self, ssl_client, ssl_server, buffer_size=1024):
-        pump(ssl_client.transport, ssl_server.transport, buffer_size)
-
-    def _do_handshake(self, client, server):
-        """ Attempt to connect client to server. Will throw a TransportException if the SSL
-        handshake fails.
-        """
-        client.connection.open()
-        server.connection.open()
-        self._pump(client, server)
-        if client.transport.closed:
-            return
-        assert client.ssl.protocol_name() is not None
-        client.connection.close()
-        server.connection.close()
-        self._pump(client, server)
-
-    def test_defaults(self):
-        if os.name=="nt":
-            raise Skipped("Windows SChannel lacks anonymous cipher support.")
-        """ By default, both the server and the client support anonymous
-        ciphers - they should connect without need for a certificate.
-        """
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        # check that no SSL connection exists
-        assert not server.ssl.cipher_name()
-        assert not client.ssl.protocol_name()
-
-        #client.transport.trace(Transport.TRACE_DRV)
-        #server.transport.trace(Transport.TRACE_DRV)
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-
-        # now SSL should be active
-        assert server.ssl.cipher_name() is not None
-        assert client.ssl.protocol_name() is not None
-
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-    def test_ssl_with_small_buffer(self):
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.connection.open()
-        server.connection.open()
-
-        small_buffer_size = 1
-        self._pump( client, server, small_buffer_size )
-
-        assert client.ssl.protocol_name() is not None
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-
-    def test_server_certificate(self):
-        """ Test that anonymous clients can still connect to a server that has
-        a certificate configured.
-        """
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert client.ssl.protocol_name() is not None
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-    def test_server_authentication(self):
-        """ Simple SSL connection with authentication of the server
-        """
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert client.ssl.protocol_name() is not None
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-    def test_certificate_fingerprint_and_subfields(self):
-        if os.name=="nt":
-            raise Skipped("Windows support for certificate fingerprint and subfield not implemented yet")
-
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
-                                                    self._testpath("ca-certificate.pem") )
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-
-        # give the client a certificate, but let's not require server authentication
-        self.client_domain.set_credentials(self._testpath("client-certificate1.pem"),
-                                           self._testpath("client-private-key1.pem"),
-                                           "client-password")
-        self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-
-        # Test the subject subfields
-        self.assertEqual("Client", server.ssl.get_cert_organization())
-        self.assertEqual("Dev", server.ssl.get_cert_organization_unit())
-        self.assertEqual("ST", server.ssl.get_cert_state_or_province())
-        self.assertEqual("US", server.ssl.get_cert_country())
-        self.assertEqual("City", server.ssl.get_cert_locality_or_city())
-        self.assertEqual("O=Server,CN=A1.Good.Server.domain.com", client.ssl.get_cert_subject())
-        self.assertEqual("O=Client,CN=127.0.0.1,C=US,ST=ST,L=City,OU=Dev", server.ssl.get_cert_subject())
-
-        self.assertEqual("f78f03ec31317c213dcf607c095242adbf067824", server.ssl.get_cert_fingerprint_sha1())
-        self.assertEqual("3836fd0d7bbc155158997ff336de29545cc1ce4137f8419062ceb8b50fd7a6f9", server.ssl.get_cert_fingerprint_sha256())
-        self.assertEqual("a8390634eb10c7a12ba3ce0837001bc6ae78c7690984f4788cf4430acdb496d5d9e02c8ec39219f5c4dcd908c34861d09481c2faf53b4ccc95dac60e623165c4",
-                         server.ssl.get_cert_fingerprint_sha512())
-        self.assertEqual("32b7bc119f61c71d368caaf9a6bf58b2", server.ssl.get_cert_fingerprint_md5())
-
-        # Test the various fingerprint algorithms
-        self.assertEqual("0aab5922c8657a7fb78402b79379506d3d7806ce", client.ssl.get_cert_fingerprint_sha1())
-        self.assertEqual("de5e0c4097f841815a769ce1a30dbe912b83711438a5aaf50001da23cee5a8a8", client.ssl.get_cert_fingerprint_sha256())
-        self.assertEqual("d0aceeb68ab9de57c9e1c21a43a4511c54ec94011e770a523a6352b1374f59c8b58adc93d5cad6f25aa125b5934309a61a25e74a5d5e0cb40b07c7468615944c",
-                         client.ssl.get_cert_fingerprint_sha512())
-        self.assertEqual("ae0ebcebc1f970fb696ef9f56e3235da", client.ssl.get_cert_fingerprint_md5())
-
-        self.assertEqual(None, client.ssl.get_cert_fingerprint(21, SSL.SHA1)) # Should be at least 41
-        self.assertEqual(None, client.ssl.get_cert_fingerprint(50, SSL.SHA256)) # Should be at least 65
-        self.assertEqual(None, client.ssl.get_cert_fingerprint(128, SSL.SHA512)) # Should be at least 129
-        self.assertEqual(None, client.ssl.get_cert_fingerprint(10, SSL.MD5)) # Should be at least 33
-        self.assertEqual(None, client.ssl._get_cert_subject_unknown_subfield())
-
-        self.assertNotEqual(None, client.ssl.get_cert_fingerprint(50, SSL.SHA1)) # Should be at least 41
-        self.assertNotEqual(None, client.ssl.get_cert_fingerprint(70, SSL.SHA256)) # Should be at least 65
-        self.assertNotEqual(None, client.ssl.get_cert_fingerprint(130, SSL.SHA512)) # Should be at least 129
-        self.assertNotEqual(None, client.ssl.get_cert_fingerprint(35, SSL.MD5)) # Should be at least 33
-        self.assertEqual(None, client.ssl._get_cert_fingerprint_unknown_hash_alg())
-
-    def test_client_authentication(self):
-        """ Force the client to authenticate.
-        """
-        # note: when requesting client auth, the server _must_ send its
-        # certificate, so make sure we configure one!
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
-                                                    self._testpath("ca-certificate.pem") )
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-
-        # give the client a certificate, but let's not require server authentication
-        self.client_domain.set_credentials(self._testpath("client-certificate.pem"),
-                                           self._testpath("client-private-key.pem"),
-                                           "client-password")
-        self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-
-        assert client.ssl.protocol_name() is not None
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-    def test_client_authentication_fail_bad_cert(self):
-        """ Ensure that the server can detect a bad client certificate.
-        """
-        # note: when requesting client auth, the server _must_ send its
-        # certificate, so make sure we configure one!
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
-                                                    self._testpath("ca-certificate.pem") )
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-
-        self.client_domain.set_credentials(self._testpath("bad-server-certificate.pem"),
-                                           self._testpath("bad-server-private-key.pem"),
-                                           "server-password")
-        self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert client.transport.closed
-        assert server.transport.closed
-        assert client.connection.state & Endpoint.REMOTE_UNINIT
-        assert server.connection.state & Endpoint.REMOTE_UNINIT
-
-    def test_client_authentication_fail_no_cert(self):
-        """ Ensure that the server will fail a client that does not provide a
-        certificate.
-        """
-        # note: when requesting client auth, the server _must_ send its
-        # certificate, so make sure we configure one!
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
-                                                    self._testpath("ca-certificate.pem") )
-        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()
-        server.connection.open()
-        self._pump( client, server )
-        assert client.transport.closed
-        assert server.transport.closed
-        assert client.connection.state & Endpoint.REMOTE_UNINIT
-        assert server.connection.state & Endpoint.REMOTE_UNINIT
-
-    def test_client_server_authentication(self):
-        """ Require both client and server to mutually identify themselves.
-        """
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
-                                                    self._testpath("ca-certificate.pem") )
-
-        self.client_domain.set_credentials(self._testpath("client-certificate.pem"),
-                                           self._testpath("client-private-key.pem"),
-                                           "client-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert client.ssl.protocol_name() is not None
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-    def test_server_only_authentication(self):
-        """ Client verifies server, but server does not verify client.
-        """
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
-
-        self.client_domain.set_credentials(self._testpath("client-certificate.pem"),
-                                           self._testpath("client-private-key.pem"),
-                                           "client-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert client.ssl.protocol_name() is not None
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-    def test_bad_server_certificate(self):
-        """ A server with a self-signed certificate that is not trusted by the
-        client.  The client should reject the server.
-        """
-        self.server_domain.set_credentials(self._testpath("bad-server-certificate.pem"),
-                                           self._testpath("bad-server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
-
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert client.transport.closed
-        assert server.transport.closed
-        assert client.connection.state & Endpoint.REMOTE_UNINIT
-        assert server.connection.state & Endpoint.REMOTE_UNINIT
-
-        del server
-        del client
-
-        # now re-try with a client that does not require peer verification
-        self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
-
-        client = SslTest.SslTestConnection( self.client_domain )
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert client.ssl.protocol_name() is not None
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-    def test_allow_unsecured_client_which_connects_unsecured(self):
-        """ Server allows an unsecured client to connect if configured.
-        """
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
-                                                    self._testpath("ca-certificate.pem") )
-        # allow unsecured clients on this connection
-        self.server_domain.allow_unsecured_client()
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-
-        # non-ssl connection
-        client = SslTest.SslTestConnection()
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert server.ssl.protocol_name() is None
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-    def test_allow_unsecured_client_which_connects_secured(self):
-        """ As per test_allow_unsecured_client_which_connects_unsecured
-            but client actually uses SSL
-        """
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
-                                                    self._testpath("ca-certificate.pem") )
-
-        self.client_domain.set_credentials(self._testpath("client-certificate.pem"),
-                                           self._testpath("client-private-key.pem"),
-                                           "client-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
-
-        # allow unsecured clients on this connection
-        #self.server_domain.allow_unsecured_client()
-
-        # client uses ssl. Server should detect this.
-        client = SslTest.SslTestConnection( self.client_domain )
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert server.ssl.protocol_name() is not None
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-
-    def test_disallow_unsecured_client(self):
-        """ Non-SSL Client is disallowed from connecting to server.
-        """
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-
-        # non-ssl connection
-        client = SslTest.SslTestConnection()
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert client.transport.closed
-        assert server.transport.closed
-        assert client.connection.state & Endpoint.REMOTE_UNINIT
-        assert server.connection.state & Endpoint.REMOTE_UNINIT
-
-    def test_session_resume(self):
-        """ Test resume of client session.
-        """
-        if os.name=="nt":
-            raise Skipped("Windows SChannel session resume not yet implemented.")
-
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER )
-
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
-
-        # details will be used in initial and subsequent connections to allow session to be resumed
-        initial_session_details = SSLSessionDetails("my-session-id")
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain, session_details=initial_session_details )
-
-        # bring up the connection and store its state
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert client.ssl.protocol_name() is not None
-
-        # cleanly shutdown the connection
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-        # destroy the existing clients
-        del client
-        del server
-
-        # now create a new set of connections, use last session id
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        # provide the details of the last session, allowing it to be resumed
-        client = SslTest.SslTestConnection( self.client_domain, session_details=initial_session_details )
-
-        #client.transport.trace(Transport.TRACE_DRV)
-        #server.transport.trace(Transport.TRACE_DRV)
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert server.ssl.protocol_name() is not None
-        if(API_LANGUAGE=="C"):
-            assert client.ssl.resume_status() == SSL.RESUME_REUSED
-        else:
-            # Java gives no way to check whether a previous session has been resumed
-            pass
-
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-        # now try to resume using an unknown session-id, expect resume to fail
-        # and a new session is negotiated
-
-        del client
-        del server
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain, session_details=SSLSessionDetails("some-other-session-id") )
-
-        client.connection.open()
-        server.connection.open()
-        self._pump( client, server )
-        assert server.ssl.protocol_name() is not None
-        if(API_LANGUAGE=="C"):
-            assert client.ssl.resume_status() == SSL.RESUME_NEW
-
-        client.connection.close()
-        server.connection.close()
-        self._pump( client, server )
-
-    def test_multiple_sessions(self):
-        """ Test multiple simultaneous active SSL sessions with bi-directional
-        certificate verification, shared across two domains.
-        """
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER,
-                                                    self._testpath("ca-certificate.pem") )
-
-        self.client_domain.set_credentials(self._testpath("client-certificate.pem"),
-                                           self._testpath("client-private-key.pem"),
-                                           "client-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
-
-        max_count = 100
-        sessions = [(SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ),
-                     SslTest.SslTestConnection( self.client_domain )) for x in
-                    range(max_count)]
-        for s in sessions:
-            s[0].connection.open()
-            self._pump( s[0], s[1] )
-
-        for s in sessions:
-            s[1].connection.open()
-            self._pump( s[1], s[0] )
-            assert s[0].ssl.cipher_name() is not None
-            assert s[1].ssl.cipher_name() == s[0].ssl.cipher_name()
-
-        for s in sessions:
-            s[1].connection.close()
-            self._pump( s[0], s[1] )
-
-        for s in sessions:
-            s[0].connection.close()
-            self._pump( s[1], s[0] )
-
-    def test_server_hostname_authentication(self):
-        """ Test authentication of the names held in the server's certificate
-        against various configured hostnames.
-        """
-        if os.name=="nt":
-            raise Skipped("PROTON-1057: disable temporarily on Windows.")
-
-        # Check the CommonName matches (case insensitive).
-        # Assumes certificate contains "CN=A1.Good.Server.domain.com"
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.ssl.peer_hostname = "a1.good.server.domain.com"
-        assert client.ssl.peer_hostname == "a1.good.server.domain.com"
-        self._do_handshake( client, server )
-        del server
-        del client
-        self.tearDown()
-
-        # Should fail on CN name mismatch:
-        self.setUp()
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                           self._testpath("server-private-key.pem"),
-                                           "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.ssl.peer_hostname = "A1.Good.Server.domain.comX"
-        self._do_handshake( client, server )
-        assert client.transport.closed
-        assert server.transport.closed
-        assert client.connection.state & Endpoint.REMOTE_UNINIT
-        assert server.connection.state & Endpoint.REMOTE_UNINIT
-        del server
-        del client
-        self.tearDown()
-
-        # Wildcarded Certificate
-        # Assumes:
-        #   1) certificate contains Server Alternate Names:
-        #        "alternate.name.one.com" and "another.name.com"
-        #   2) certificate has wildcarded CommonName "*.prefix*.domain.com"
-        #
-
-        # Pass: match an alternate
-        self.setUp()
-        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
-                                           self._testpath("server-wc-private-key.pem"),
-                                           "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.ssl.peer_hostname = "alternate.Name.one.com"
-        self._do_handshake( client, server )
-        del client
-        del server
-        self.tearDown()
-
-        # Pass: match an alternate
-        self.setUp()
-        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
-                                    self._testpath("server-wc-private-key.pem"),
-                                    "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.ssl.peer_hostname = "ANOTHER.NAME.COM"
-        self._do_handshake(client, server)
-        del client
-        del server
-        self.tearDown()
-
-        # Pass: match the pattern
-        self.setUp()
-        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
-                                    self._testpath("server-wc-private-key.pem"),
-                                    "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.ssl.peer_hostname = "SOME.PREfix.domain.COM"
-        self._do_handshake( client, server )
-        del client
-        del server
-        self.tearDown()
-
-        # Pass: match the pattern
-        self.setUp()
-        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
-                                    self._testpath("server-wc-private-key.pem"),
-                                    "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.ssl.peer_hostname = "FOO.PREfixZZZ.domain.com"
-        self._do_handshake( client, server )
-        del client
-        del server
-        self.tearDown()
-
-        # Fail: must match prefix on wildcard
-        self.setUp()
-        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
-                                    self._testpath("server-wc-private-key.pem"),
-                                    "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.ssl.peer_hostname = "FOO.PREfi.domain.com"
-        self._do_handshake( client, server )
-        assert client.transport.closed
-        assert server.transport.closed
-        assert client.connection.state & Endpoint.REMOTE_UNINIT
-        assert server.connection.state & Endpoint.REMOTE_UNINIT
-        del server
-        del client
-        self.tearDown()
-
-        # Fail: leading wildcards are not optional
-        self.setUp()
-        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
-                                    self._testpath("server-wc-private-key.pem"),
-                                    "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        client.ssl.peer_hostname = "PREfix.domain.COM"
-        self._do_handshake( client, server )
-        assert client.transport.closed
-        assert server.transport.closed
-        assert client.connection.state & Endpoint.REMOTE_UNINIT
-        assert server.connection.state & Endpoint.REMOTE_UNINIT
-        self.tearDown()
-
-        # Pass: ensure that the user can give an alternate name that overrides
-        # the connection's configured hostname
-        self.setUp()
-        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
-                                    self._testpath("server-wc-private-key.pem"),
-                                    "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection(self.server_domain, mode=Transport.SERVER)
-        client = SslTest.SslTestConnection(self.client_domain,
-                                           conn_hostname="This.Name.Does.not.Match",
-                                           ssl_peername="alternate.name.one.com")
-        self._do_handshake(client, server)
-        del client
-        del server
-        self.tearDown()
-
-        # Pass: ensure that the hostname supplied by the connection is used if
-        # none has been specified for the SSL instance
-        self.setUp()
-        self.server_domain.set_credentials(self._testpath("server-certificate.pem"),
-                                    self._testpath("server-private-key.pem"),
-                                    "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection(self.server_domain, mode=Transport.SERVER)
-        client = SslTest.SslTestConnection(self.client_domain,
-                                           conn_hostname="a1.good.server.domain.com")
-        self._do_handshake(client, server)
-        del client
-        del server
-        self.tearDown()
-
-    def test_server_hostname_authentication_2(self):
-        """Initially separated from test_server_hostname_authentication
-        above to force Windows checking and sidestep PROTON-1057 exclusion.
-        """
-
-        # Fail for a null peer name.
-        self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"),
-                                    self._testpath("server-wc-private-key.pem"),
-                                    "server-password")
-        self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME )
-
-        server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER )
-        client = SslTest.SslTestConnection( self.client_domain )
-
-        # Next line results in an eventual pn_ssl_set_peer_hostname(client.ssl._ssl, None)
-        client.ssl.peer_hostname = None
-        self._do_handshake( client, server )
-        assert client.transport.closed
-        assert server.transport.closed
-        assert client.connection.state & Endpoint.REMOTE_UNINIT
-        assert server.connection.state & Endpoint.REMOTE_UNINIT
-        self.tearDown()
-
-    def test_defaults_messenger_app(self):
-        """ Test an SSL connection using the Messenger apps (no certificates)
-        """
-        if os.name=="nt":
-            raise Skipped("Windows SChannel lacks anonymous cipher support.")
-        port = common.free_tcp_ports()[0]
-
-        receiver = common.MessengerReceiverC()
-        receiver.subscriptions = ["amqps://~0.0.0.0:%s" % port]
-        receiver.receive_count = 1
-        receiver.timeout = self.timeout
-        receiver.start()
-
-        sender = common.MessengerSenderC()
-        sender.targets = ["amqps://0.0.0.0:%s/X" % port]
-        sender.send_count = 1
-        sender.timeout = self.timeout
-        sender.start()
-        sender.wait()
-        assert sender.status() == 0, "Command '%s' failed" % str(sender.cmdline())
-
-        receiver.wait()
-        assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline())
-
-    def test_server_authentication_messenger_app(self):
-        """ Test an SSL authentication using the Messenger apps.
-        """
-        port = common.free_tcp_ports()[0]
-
-        receiver = common.MessengerReceiverC()
-        receiver.subscriptions = ["amqps://~0.0.0.0:%s" % port]
-        receiver.receive_count = 1
-        receiver.timeout = self.timeout
-        # Note hack - by default we use the client-certificate for the
-        # _server_ because the client-certificate's common name field
-        # is "127.0.0.1", which will match the target address used by
-        # the sender.
-        receiver.certificate = self._testpath("client-certificate.pem")
-        receiver.privatekey = self._testpath("client-private-key.pem")
-        receiver.password = "client-password"
-        receiver.start()
-
-        sender = common.MessengerSenderC()
-        sender.targets = ["amqps://127.0.0.1:%s/X" % port]
-        sender.send_count = 1
-        sender.timeout = self.timeout
-        sender.ca_db = self._testpath("ca-certificate.pem")
-        sender.start()
-        sender.wait()
-        assert sender.status() == 0, "Command '%s' failed" % str(sender.cmdline())
-
-        receiver.wait()
-        assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline())
-
-    def DISABLED_test_defaults_valgrind(self):
-        """ Run valgrind over a simple SSL connection (no certificates)
-        """
-        # the openssl libraries produce far too many valgrind errors to be
-        # useful.  AFAIK, there is no way to wriate a valgrind suppression
-        # expression that will ignore all errors from a given library.
-        # Until we can, skip this test.
-        port = common.free_tcp_ports()[0]
-
-        receiver = common.MessengerReceiverValgrind()
-        receiver.subscriptions = ["amqps://~127.0.0.1:%s" % port]
-        receiver.receive_count = 1
-        receiver.timeout = self.timeout
-        receiver.start()
-
-        sender = common.MessengerSenderValgrind()
-        sender.targets = ["amqps://127.0.0.1:%s/X" % port]
-        sender.send_count = 1
-        sender.timeout = self.timeout
-        sender.start()
-        sender.wait()
-        assert sender.status() == 0, "Command '%s' failed" % str(sender.cmdline())
-
-        receiver.wait()
-        assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline())
-
-        # self.server_domain.set_credentials(self._testpath("client-certificate.pem"),
-        #                                    self._testpath("client-private-key.pem"),
-        #                                    "client-password")
-
-        # self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        # self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
-
-    def test_singleton(self):
-        """Verify that only a single instance of SSL can exist per Transport"""
-        transport = Transport()
-        ssl1 = SSL(transport, self.client_domain)
-        ssl2 = transport.ssl(self.client_domain)
-        ssl3 = transport.ssl(self.client_domain)
-        assert ssl1 is ssl2
-        assert ssl1 is ssl3
-        transport = Transport()
-        ssl1 = transport.ssl(self.client_domain)
-        ssl2 = SSL(transport, self.client_domain)
-        assert ssl1 is ssl2
-        # catch attempt to re-configure existing SSL
-        try:
-            ssl3 = SSL(transport, self.server_domain)
-            assert False, "Expected error did not occur!"
-        except SSLException:
-            pass

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/README.txt
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/README.txt b/tests/python/proton_tests/ssl_db/README.txt
deleted file mode 100644
index 20c92b2..0000000
--- a/tests/python/proton_tests/ssl_db/README.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-The following certificate files are used by the SSL unit tests (ssl.py):
-
-ca-certificate.pem - contains the public certificate identifying a "trusted" Certificate
-Authority.  This certificate is used to sign the certificates that identify the SSL
-servers and clients run by the tests.
-
-client-certificate.pem - the public certificate used to identify the client.  Signed by
-the CA.
-
-client-private-key.pem - encrypted key used to create client-certificate.pem.  Password is
-"client-password"
-
-server-certificate.pem - the public certificate used to identify the server.  Signed by
-the CA.  The CommonName is "A1.Good.Server.domain.com", and is checked by some unit tests.
-
-server-private-key.pem - encrypted key used to create server-certificate.pem. Password is
-"server-password"
-
-bad-server-certificate.pem, bad-server-private-key.pem - a certificate/key that is not trusted by the client, for negative test.
-
-server-wc-certificate.pem and server-wc-private-key.pem - similar to
-server-certificate.pem and server-private-key.pem, but contains Subject Alternate Name
-entries, and a wildcard CommonName.  Used for certificate name checking tests.
-
-These certificates have been created using the OpenSSL tool.
-
-The following bash script can be used to create these certificates (requires keytool from Java 1.7, and openssl):
-
---8<--
-#!/bin/bash
-#set -x
-
-rm -f *.pem *.pkcs12
-
-# Create a self-signed certificate for the CA, and a private key to sign certificate requests:
-keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -genkey -dname "O=Trust Me Inc.,CN=Trusted.CA.com" -validity 99999 -ext bc:c=ca:true,pathlen:0 -ext ku:c=digitalSignature,keyCertSign -ext ExtendedkeyUsage=serverAuth,clientAuth
-openssl pkcs12 -nokeys -passin pass:ca-password -in ca.pkcs12 -passout pass:ca-password -out ca-certificate.pem
-
-# Create a certificate request for the server certificate.  Use the CA's certificate to sign it:
-keytool -storetype pkcs12 -keystore server.pkcs12 -storepass server-password -alias server-certificate -keypass server-password -genkey  -dname "O=Server,CN=A1.Good.Server.domain.com" -validity 99999
-keytool -storetype pkcs12 -keystore server.pkcs12 -storepass server-password -alias server-certificate -keypass server-password -certreq -file server-request.pem
-keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile server-request.pem -outfile server-certificate.pem
-openssl pkcs12 -nocerts -passin pass:server-password -in server.pkcs12 -passout pass:server-password -out server-private-key.pem
-
-# Create a certificate request for the client certificate.  Use the CA's certificate to sign it:
-keytool -storetype pkcs12 -keystore client.pkcs12 -storepass client-password -alias client-certificate -keypass client-password -genkey  -dname "O=Client,CN=127.0.0.1" -validity 99999
-keytool -storetype pkcs12 -keystore client.pkcs12 -storepass client-password -alias client-certificate -keypass client-password -certreq -file client-request.pem
-keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile client-request.pem -outfile client-certificate.pem
-openssl pkcs12 -nocerts -passin pass:client-password -in client.pkcs12 -passout pass:client-password -out client-private-key.pem
-
-# Create another client certificate with a different subject line
-keytool -storetype pkcs12 -keystore client1.pkcs12 -storepass client-password -alias client-certificate1 -keypass client-password -genkey  -dname "O=Client,CN=127.0.0.1,C=US,ST=ST,L=City,OU=Dev" -validity 99999
-keytool -storetype pkcs12 -keystore client1.pkcs12 -storepass client-password -alias client-certificate1 -keypass client-password -certreq -file client-request1.pem
-keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile client-request1.pem -outfile client-certificate1.pem
-openssl pkcs12 -nocerts -passin pass:client-password -in client1.pkcs12 -passout pass:client-password -out client-private-key1.pem
-
-# Create a "bad" certificate - not signed by a trusted authority
-keytool -storetype pkcs12 -keystore bad-server.pkcs12 -storepass server-password -alias bad-server -keypass server-password -genkey -dname "O=Not Trusted Inc,CN=127.0.0.1" -validity 99999
-openssl pkcs12 -nocerts -passin pass:server-password -in bad-server.pkcs12 -passout pass:server-password -out bad-server-private-key.pem
-openssl pkcs12 -nokeys  -passin pass:server-password -in bad-server.pkcs12 -passout pass:server-password -out bad-server-certificate.pem
-
-# Create a server certificate with several alternate names, including a wildcarded common name:
-keytool -ext san=dns:alternate.name.one.com,dns:another.name.com -storetype pkcs12 -keystore server-wc.pkcs12 -storepass server-password -alias server-wc-certificate -keypass server-password -genkeypair -dname "O=Server,CN=*.prefix*.domain.com" -validity 99999
-keytool -ext san=dns:alternate.name.one.com,dns:another.name.com -storetype pkcs12 -keystore server-wc.pkcs12 -storepass server-password -alias server-wc-certificate -keypass server-password -certreq -file server-wc-request.pem
-keytool -ext san=dns:alternate.name.one.com,dns:another.name.com  -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile server-wc-request.pem -outfile server-wc-certificate.pem
-openssl pkcs12 -nocerts -passin pass:server-password -in server-wc.pkcs12 -passout pass:server-password -out server-wc-private-key.pem
-
-# Create pkcs12 versions of the above certificates (for Windows SChannel)
-# The CA certificate store/DB is created without public keys.
-# Give the "p12" files the same base name so the tests can just change the extension to switch between platforms.
-# These certificates might work for OpenSSL <-> SChannel interop tests, but note that the DH cypher suite
-# overlap is poor between platforms especially for older Windows versions.  RSA certificates are better for
-# interop (or PFS-friendly certificates on newer platforms).
-openssl pkcs12 -export -out ca-certificate.p12 -in ca-certificate.pem -name ca-certificate -nokeys -passout pass:
-openssl pkcs12 -export -out server-certificate.p12 -passin pass:server-password -passout pass:server-password -inkey server-private-key.pem -in server-certificate.pem -name server-certificate
-openssl pkcs12 -export -out client-certificate.p12 -passin pass:client-password -passout pass:client-password -inkey client-private-key.pem -in client-certificate.pem -name client-certificate
-openssl pkcs12 -export -out client-certificate1.p12 -passin pass:client-password -passout pass:client-password -inkey client-private-key1.pem -in client-certificate1.pem -name client-certificate1
-openssl pkcs12 -export -out bad-server-certificate.p12 -passin pass:server-password -passout pass:server-password -inkey bad-server-private-key.pem -in bad-server-certificate.pem -name bad-server
-openssl pkcs12 -export -out server-wc-certificate.p12 -passin pass:server-password -passout pass:server-password -inkey server-wc-private-key.pem -in server-wc-certificate.pem -name server-wc-certificate

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/bad-server-certificate.p12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/bad-server-certificate.p12 b/tests/python/proton_tests/ssl_db/bad-server-certificate.p12
deleted file mode 100644
index 7906831..0000000
Binary files a/tests/python/proton_tests/ssl_db/bad-server-certificate.p12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/bad-server-certificate.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/bad-server-certificate.pem b/tests/python/proton_tests/ssl_db/bad-server-certificate.pem
deleted file mode 100644
index 0aacfa2..0000000
--- a/tests/python/proton_tests/ssl_db/bad-server-certificate.pem
+++ /dev/null
@@ -1,22 +0,0 @@
-Bag Attributes
-    friendlyName: bad-server
-    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 38 32 39 36 
-subject=/CN=127.0.0.1/O=Not Trusted Inc
-issuer=/CN=127.0.0.1/O=Not Trusted Inc
------BEGIN CERTIFICATE-----
-MIICuzCCAnmgAwIBAgIELMpW4jALBgcqhkjOOAQDBQAwLjESMBAGA1UEAxMJMTI3
-LjAuMC4xMRgwFgYDVQQKEw9Ob3QgVHJ1c3RlZCBJbmMwIBcNMTcwODAyMjE1MzM4
-WhgPMjI5MTA1MTcyMTUzMzhaMC4xEjAQBgNVBAMTCTEyNy4wLjAuMTEYMBYGA1UE
-ChMPTm90IFRydXN0ZWQgSW5jMIIBuDCCASwGByqGSM44BAEwggEfAoGBAP1/U4Ed
-dRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs
-14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208Ue
-wwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BY
-HPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+Zx
-BxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx
-+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYUAAoGBAK3E
-5j/UaiVHJYAf3DAIl5hjTZcChTp57GjODdfDteHeDh85HFyW0kxmXyhpUdODzAgG
-THhpxy/+Kkd8jmUBVFnU1EXByvGORBfnJkMTkuhmk9veytxlskQ0tQV8gmRNb0Xe
-hie7T9UT8TQJy9mPS74pSuviFSx0Hz0dKGi0eVUYoyEwHzAdBgNVHQ4EFgQUg2PE
-qycdV1oxVaA33ULDrVdSjhkwCwYHKoZIzjgEAwUAAy8AMCwCFGybqSwG3TauRJVw
-XA/xeSxpYbcBAhQ6ylf9XZAvM7tMyQQTcDAkmt+YWQ==
------END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/bad-server-private-key.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/bad-server-private-key.pem b/tests/python/proton_tests/ssl_db/bad-server-private-key.pem
deleted file mode 100644
index 3a30d41..0000000
--- a/tests/python/proton_tests/ssl_db/bad-server-private-key.pem
+++ /dev/null
@@ -1,15 +0,0 @@
-Bag Attributes
-    friendlyName: bad-server
-    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 38 32 39 36 
-Key Attributes: <No Attributes>
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIBljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIqgLLe7iT+1wCAggA
-MBQGCCqGSIb3DQMHBAhg98ZJQMtngwSCAVCdhdOMr+VVTNaIPSy4nSwdRTlXIuRa
-4wPi+07mToJmEtGfpJ4MPjDF9yRptVQI4RoN/RrLl0WX/HNZ5U4JluL0j68+JB1d
-MoeSRiRc+Yd2vxey8reBrvx1m1mB3LXvm38oZVDFrQ9FNGK09EtTLN1rqckr1fxQ
-Imcvb63nu5UZB8WMCVfKqe9Zm9dQlsSlp3M5OCRm296Xsr0eWwe2W1/rJiKMZN7x
-eJMf4pWVrBHoi6VJHAEA7ZvhRfcHkSbyze5ouDpKbMZS9gq38Hs4d+wkxe9x3emx
-6OvppcpBolZhntF1vJXUXMc6D5Pw3mGEsRGwcMJqWCc8XJTkyP0ylNFNyaHaz0oC
-jSWmUu0s5628K+m8nGY4X7msfOddTA16W6mODjE2ddlTqwTFu2CYBk3WbprBRXo0
-ionZQTPTqcM0UR3KyF9CHRZbnQ/d7bk57/w=
------END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/bad-server.pkcs12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/bad-server.pkcs12 b/tests/python/proton_tests/ssl_db/bad-server.pkcs12
deleted file mode 100644
index dea2143..0000000
Binary files a/tests/python/proton_tests/ssl_db/bad-server.pkcs12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/ca-certificate.p12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/ca-certificate.p12 b/tests/python/proton_tests/ssl_db/ca-certificate.p12
deleted file mode 100644
index 767b24d..0000000
Binary files a/tests/python/proton_tests/ssl_db/ca-certificate.p12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/ca-certificate.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/ca-certificate.pem b/tests/python/proton_tests/ssl_db/ca-certificate.pem
deleted file mode 100644
index 1461f25..0000000
--- a/tests/python/proton_tests/ssl_db/ca-certificate.pem
+++ /dev/null
@@ -1,24 +0,0 @@
-Bag Attributes
-    friendlyName: ca
-    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 36 34 37 32 
-subject=/CN=Trusted.CA.com/O=Trust Me Inc.
-issuer=/CN=Trusted.CA.com/O=Trust Me Inc.
------BEGIN CERTIFICATE-----
-MIIDBDCCAsKgAwIBAgIEBGGY1zALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1
-c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTcwODAyMjE1
-MzM2WhgPMjI5MTA1MTcyMTUzMzZaMDExFzAVBgNVBAMTDlRydXN0ZWQuQ0EuY29t
-MRYwFAYDVQQKEw1UcnVzdCBNZSBJbmMuMIIBuDCCASwGByqGSM44BAEwggEfAoGB
-AP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6
-MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E
-+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC
-ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeO
-utRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/
-C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYUA
-AoGBALsRT+tH1c+TC78EYtPh+KQ0DosKKtxeSRos4eQ49erdI+tYhzeqN3Ebmeky
-TWfGjjU64PGRFDNGjpf9l7Yo22jk9U5zIFkFp5gP9DVBHrOrh8mdT+/oBhhVHxI5
-rWLqSjI/zXhRzRwueR81p0D3XJlV3g/xlOlWALoRnUWpDAo3o2QwYjASBgNVHRMB
-Af8ECDAGAQH/AgEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV
-HQ8BAf8EBAMCAoQwHQYDVR0OBBYEFLI2ezwilYHGS5MRPMWlifHH+Y5qMAsGByqG
-SM44BAMFAAMvADAsAhRxomjEvDfhe1p+D6KLc0IGjDNgtgIUIZXb0/Fpzy6dpCwe
-Ay+soxvpfMU=
------END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/ca.pkcs12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/ca.pkcs12 b/tests/python/proton_tests/ssl_db/ca.pkcs12
deleted file mode 100644
index d9ca00c..0000000
Binary files a/tests/python/proton_tests/ssl_db/ca.pkcs12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/client-certificate.p12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/client-certificate.p12 b/tests/python/proton_tests/ssl_db/client-certificate.p12
deleted file mode 100644
index 82271f9..0000000
Binary files a/tests/python/proton_tests/ssl_db/client-certificate.p12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/client-certificate.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/client-certificate.pem b/tests/python/proton_tests/ssl_db/client-certificate.pem
deleted file mode 100644
index 5b4aa86..0000000
--- a/tests/python/proton_tests/ssl_db/client-certificate.pem
+++ /dev/null
@@ -1,18 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC1jCCApOgAwIBAgIEeg2f8DALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1
-c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTcwODAyMjE1
-MzM3WhgPMjI5MTA1MTcyMTUzMzdaMCUxEjAQBgNVBAMTCTEyNy4wLjAuMTEPMA0G
-A1UEChMGQ2xpZW50MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9K
-nC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00
-b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNa
-FpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA
-9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ
-FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7
-zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAJ3g1ohpHgoxH
-3Yj0SIfiPcUaM5FIszemFwQ2FZoG/J7MiVIw442JheTR/iEB3LYheHBp7ToqhaMY
-NYidcxxUzgZJs3worXqAuUgDdbDcW6AjQ4olyGVt7sX9OL2amMq9BFCIt7SlyDKW
-8Accx46H+8BffMdCu56yw5WQtZ3cPD2jQjBAMB8GA1UdIwQYMBaAFLI2ezwilYHG
-S5MRPMWlifHH+Y5qMB0GA1UdDgQWBBQg7FbClmtrSAHA9lR8E7uexl5p1jALBgcq
-hkjOOAQDBQADMAAwLQIVAIpUbUYyA3DisZyENQwcN0rDQ+FyAhRPcfg9Slb6MfO4
-SBFqOiesk+cpqw==
------END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/client-certificate1.p12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/client-certificate1.p12 b/tests/python/proton_tests/ssl_db/client-certificate1.p12
deleted file mode 100644
index d35f88f..0000000
Binary files a/tests/python/proton_tests/ssl_db/client-certificate1.p12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/client-certificate1.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/client-certificate1.pem b/tests/python/proton_tests/ssl_db/client-certificate1.pem
deleted file mode 100644
index f4549a4..0000000
--- a/tests/python/proton_tests/ssl_db/client-certificate1.pem
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDDDCCAsqgAwIBAgIEBmzTzzALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1
-c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTcwODAyMjE1
-MzM4WhgPMjI5MTA1MTcyMTUzMzhaMFwxDDAKBgNVBAsTA0RldjENMAsGA1UEBxME
-Q2l0eTELMAkGA1UECBMCU1QxCzAJBgNVBAYTAlVTMRIwEAYDVQQDEwkxMjcuMC4w
-LjExDzANBgNVBAoTBkNsaWVudDCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OB
-HXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tV
-bNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPF
-HsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvw
-WBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/m
-cQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi
-8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GEAAKBgHVu
-urVq1FFws/JN+I3yfA2RVmFwlYJID8yyO9lkHBPBDE0dqfFBF6F3nwsCiZF0n/v4
-od6MuuRSplV4kZH0jOOVw7e9cF2RNd/KahsIpm/Oq5aosm6W7KDK/xIwNyW+3DFt
-TGDTOZ6ejVMgGR2rAD+FEp2yycJACQBP1GtTSFXTo0IwQDAfBgNVHSMEGDAWgBSy
-Nns8IpWBxkuTETzFpYnxx/mOajAdBgNVHQ4EFgQUz4cx+zNqsCmWpBU2dw8GHO33
-+eEwCwYHKoZIzjgEAwUAAy8AMCwCFCsfHJPB4Tq6qX5U+DZBc3jmLBiXAhRF17Dz
-fq+AxqyQ9PvTtH3UbFh1hQ==
------END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/client-private-key.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/client-private-key.pem b/tests/python/proton_tests/ssl_db/client-private-key.pem
deleted file mode 100644
index b6256e7..0000000
--- a/tests/python/proton_tests/ssl_db/client-private-key.pem
+++ /dev/null
@@ -1,15 +0,0 @@
-Bag Attributes
-    friendlyName: client-certificate
-    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 37 32 33 39 
-Key Attributes: <No Attributes>
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIBljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIHmVKa1dEtm4CAggA
-MBQGCCqGSIb3DQMHBAgpc0Ay33xL9ASCAVBJ8D5DVRd0d6t3gSvTFBAflpUROv2/
-pQlMLGbGlJIoEPyMIc9/GcgS7U19nMdoJjI1TuT/hGwObualnRRjY6KL5cbK2oUQ
-371yUs6jGIQxtCeb1WgKpA/FKw9jRO7Tg5ztObItPiSQvkOcssfdRJYI1+W+ovj+
-j1BKMkJu197twIChYaz+3ppJzrh3qlqFgdRdE9H04ffWpNaZ6aOIIJHPMuZ8FScu
-bQyvD9JjI+JWJUaCyp/3dxxxVrZ3vu8i6LmrL6Nm9IkJtFMZOfgPkoRLML2DWKqB
-1qLk/Z45/THXDAxrPggFfqMvuctwJmtAGvo3MIbfCi+aewJE6/DjlSHDv6wGvOGB
-T5golvZ5siahHqwmufSQG8ZTsGcpu/jCA5ipIvcTVgWIxscNc2Yx9FDNWVNzUcTy
-ctRX6DS+s7rAy9ISjch4BbAtI7yALFt63eU=
------END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/client-private-key1.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/client-private-key1.pem b/tests/python/proton_tests/ssl_db/client-private-key1.pem
deleted file mode 100644
index 544d2ae..0000000
--- a/tests/python/proton_tests/ssl_db/client-private-key1.pem
+++ /dev/null
@@ -1,15 +0,0 @@
-Bag Attributes
-    friendlyName: client-certificate1
-    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 37 37 37 32 
-Key Attributes: <No Attributes>
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIBljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIg1n9vdGttqoCAggA
-MBQGCCqGSIb3DQMHBAgRjlrRQfGcLQSCAVChui/M+36/e0WzeM79aJV7YZds/OJY
-gprtJ2g5Cxb1L9hymwgxJtOAaRUqLUcfLHcKSxA+MaB+Ij+/8TH+miq0zZ9q0jZV
-BAm56FNgUjW0nPLueTNhWzVVfQU6H9Tj33OuKm1PQo84Af3OPMtE03pvGDPEAPbH
-a72HUgZyI7WTux4wpxfvUEVkT5OXgBHrFlqXiHHCI+9kqBXMCV3oHgZBcO+dqPKS
-rlaTY7xoQWLenB6EQeYopMA2GNUVtzB3y6/nX2z0Yp5oHqKPBNOyFlVmwCrENN1/
-qnrFfzVbnksWLKhg9O+TPsId1UIZVvBh67y5N5IZRrpuE03qd2BScKM/Tn6vkWNB
-Eus74Vba5vw9prauRC45FVgDe2YYYoULYPfhXWSiiWHDNKOBlz3l3hGlZsC8wKe5
-QlV5bVcOTfGIaBkD7SQyfRjMr8SWj4WMw1M=
------END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/client-request.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/client-request.pem b/tests/python/proton_tests/ssl_db/client-request.pem
deleted file mode 100644
index 1265153..0000000
--- a/tests/python/proton_tests/ssl_db/client-request.pem
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN NEW CERTIFICATE REQUEST-----
-MIICWTCCAhcCAQAwJTESMBAGA1UEAxMJMTI3LjAuMC4xMQ8wDQYDVQQKEwZDbGll
-bnQwggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I8
-70QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWk
-n5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HX
-Ku/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8
-q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fP
-CTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD
-3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhAACgYAneDWiGkeCjEfdiPRIh+I9xRoz
-kUizN6YXBDYVmgb8nsyJUjDjjYmF5NH+IQHctiF4cGntOiqFoxg1iJ1zHFTOBkmz
-fCiteoC5SAN1sNxboCNDiiXIZW3uxf04vZqYyr0EUIi3tKXIMpbwBxzHjof7wF98
-x0K7nrLDlZC1ndw8PaAwMC4GCSqGSIb3DQEJDjEhMB8wHQYDVR0OBBYEFCDsVsKW
-a2tIAcD2VHwTu57GXmnWMAsGByqGSM44BAMFAAMvADAsAhQY5Zy4fQcy/SZOJ2Ix
-cl3/QfimvQIUVvSdet7NKWzMQoBDhlJTdTzJvE8=
------END NEW CERTIFICATE REQUEST-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/client-request1.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/client-request1.pem b/tests/python/proton_tests/ssl_db/client-request1.pem
deleted file mode 100644
index c73275f..0000000
--- a/tests/python/proton_tests/ssl_db/client-request1.pem
+++ /dev/null
@@ -1,16 +0,0 @@
------BEGIN NEW CERTIFICATE REQUEST-----
-MIICkTCCAk4CAQAwXDEMMAoGA1UECxMDRGV2MQ0wCwYDVQQHEwRDaXR5MQswCQYD
-VQQIEwJTVDELMAkGA1UEBhMCVVMxEjAQBgNVBAMTCTEyNy4wLjAuMTEPMA0GA1UE
-ChMGQ2xpZW50MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s
-5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/Jm
-YLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy
-9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+Gg
-hdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj
-6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTx
-vqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAdW66tWrUUXCz8k34
-jfJ8DZFWYXCVgkgPzLI72WQcE8EMTR2p8UEXoXefCwKJkXSf+/ih3oy65FKmVXiR
-kfSM45XDt71wXZE138pqGwimb86rlqiybpbsoMr/EjA3Jb7cMW1MYNM5np6NUyAZ
-HasAP4USnbLJwkAJAE/Ua1NIVdOgMDAuBgkqhkiG9w0BCQ4xITAfMB0GA1UdDgQW
-BBTPhzH7M2qwKZakFTZ3DwYc7ff54TALBgcqhkjOOAQDBQADMAAwLQIUFs17HaTm
-vest72/4Caoo1sH39n0CFQCR680PPwr3lZ5jjEOp+n4htQNUvw==
------END NEW CERTIFICATE REQUEST-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/client.pkcs12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/client.pkcs12 b/tests/python/proton_tests/ssl_db/client.pkcs12
deleted file mode 100644
index 575a551..0000000
Binary files a/tests/python/proton_tests/ssl_db/client.pkcs12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/client1.pkcs12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/client1.pkcs12 b/tests/python/proton_tests/ssl_db/client1.pkcs12
deleted file mode 100644
index 0e7c888..0000000
Binary files a/tests/python/proton_tests/ssl_db/client1.pkcs12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/server-certificate.p12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/server-certificate.p12 b/tests/python/proton_tests/ssl_db/server-certificate.p12
deleted file mode 100644
index cacfa89..0000000
Binary files a/tests/python/proton_tests/ssl_db/server-certificate.p12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/server-certificate.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/server-certificate.pem b/tests/python/proton_tests/ssl_db/server-certificate.pem
deleted file mode 100644
index e324df5..0000000
--- a/tests/python/proton_tests/ssl_db/server-certificate.pem
+++ /dev/null
@@ -1,18 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC5jCCAqSgAwIBAgIEX8z6MDALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1
-c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTcwODAyMjE1
-MzM3WhgPMjI5MTA1MTcyMTUzMzdaMDUxIjAgBgNVBAMTGUExLkdvb2QuU2VydmVy
-LmRvbWFpbi5jb20xDzANBgNVBAoTBlNlcnZlcjCCAbgwggEsBgcqhkjOOAQBMIIB
-HwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6
-v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58ao
-phUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvM
-spK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4Jn
-UVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1
-kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kq
-A4GFAAKBgQCERpy6RrkNHpgXT/uL9gN/IgwY7kp3Iwzr1lrqo+HqmydE+Cz9uqPH
-VyxjX7nHVrdwl7xgsoki3QyoKcrZfTL1oS79kodWG7t6CyOtj2L3KGMUdIlqWepZ
-wzCKTWrb07VjpqhMh0Qh8+IqEmvfC/4UVOec9alX0NO/ckDbIBhITqNCMEAwHwYD
-VR0jBBgwFoAUsjZ7PCKVgcZLkxE8xaWJ8cf5jmowHQYDVR0OBBYEFBhEDdcBRqn5
-wFEbAad559yrQPE7MAsGByqGSM44BAMFAAMvADAsAhRuMRxWMKxy3USjfSFn47H4
-Z5VIHgIUB2i6+RQi7dHOEQYKKmxdQvAPA9M=
------END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/server-private-key.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/server-private-key.pem b/tests/python/proton_tests/ssl_db/server-private-key.pem
deleted file mode 100644
index e68a39d..0000000
--- a/tests/python/proton_tests/ssl_db/server-private-key.pem
+++ /dev/null
@@ -1,15 +0,0 @@
-Bag Attributes
-    friendlyName: server-certificate
-    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 36 36 35 36 
-Key Attributes: <No Attributes>
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIBljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI6jwDH/9bZYMCAggA
-MBQGCCqGSIb3DQMHBAgbIQ8UrRfmAgSCAVDejPh9sT2PMvDjjzXG6xpSmBPNZRiz
-f2k2a9EaI8L4xadveiZTzOpk2C/nltMCNY2Vwf/LMtbvcLiadBRWM/4Uf5fvL/94
-zlKE77wPSWK1R+btZm0KIaA+EPAvnIGcjHlcSU58eQexwVlMXJ9pdeHm9KWbV1D+
-PjrlJ+SDq7OSGprTCz9r+gQ7Fy2Oe9OKc92tE29QD2AZXtSodvY9CosXCx4cqXr3
-ey+HXmVXJohsL89NycL80TvkxppqZ1hT3DZMkrFg2jFPz505rzE48y62FMoKNCjQ
-6HXvsniWYXf7ipr+A4/diSSMBr/zmA+H+ZHKlNO8FJqZ8eI1eqRO+PjO1VV9bbG0
-lYoeoFu0Y1xw6V2jLYnFF1mTCC6kegl6kruvnwO7Oy+6kPEvDrejuI6uozW2etej
-cBq1lUK5QNKSoaB7Qw+2qlyFg/KFwXXDBqk=
------END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/server-request.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/server-request.pem b/tests/python/proton_tests/ssl_db/server-request.pem
deleted file mode 100644
index da57b89..0000000
--- a/tests/python/proton_tests/ssl_db/server-request.pem
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN NEW CERTIFICATE REQUEST-----
-MIICazCCAigCAQAwNTEiMCAGA1UEAxMZQTEuR29vZC5TZXJ2ZXIuZG9tYWluLmNv
-bTEPMA0GA1UEChMGU2VydmVyMIIBuDCCASwGByqGSM44BAEwggEfAoGBAP1/U4Ed
-dRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs
-14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208Ue
-wwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BY
-HPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+Zx
-BxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx
-+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYUAAoGBAIRG
-nLpGuQ0emBdP+4v2A38iDBjuSncjDOvWWuqj4eqbJ0T4LP26o8dXLGNfucdWt3CX
-vGCyiSLdDKgpytl9MvWhLv2Sh1Ybu3oLI62PYvcoYxR0iWpZ6lnDMIpNatvTtWOm
-qEyHRCHz4ioSa98L/hRU55z1qVfQ079yQNsgGEhOoDAwLgYJKoZIhvcNAQkOMSEw
-HzAdBgNVHQ4EFgQUGEQN1wFGqfnAURsBp3nn3KtA8TswCwYHKoZIzjgEAwUAAzAA
-MC0CFFIXSYKFVq90wR3lH+KCwvL+j0A4AhUAlxeczUtqTQFeGXFsDwIGO+5/uA4=
------END NEW CERTIFICATE REQUEST-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/server-wc-certificate.p12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/server-wc-certificate.p12 b/tests/python/proton_tests/ssl_db/server-wc-certificate.p12
deleted file mode 100644
index 3f8a53d..0000000
Binary files a/tests/python/proton_tests/ssl_db/server-wc-certificate.p12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/server-wc-certificate.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/server-wc-certificate.pem b/tests/python/proton_tests/ssl_db/server-wc-certificate.pem
deleted file mode 100644
index f48c6fe..0000000
--- a/tests/python/proton_tests/ssl_db/server-wc-certificate.pem
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDFTCCAtOgAwIBAgIEVTK/cTALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1
-c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTcwODAyMjE1
-MzM4WhgPMjI5MTA1MTcyMTUzMzhaMDAxHTAbBgNVBAMMFCoucHJlZml4Ki5kb21h
-aW4uY29tMQ8wDQYDVQQKEwZTZXJ2ZXIwggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA
-/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow
-9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7
-g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi
-64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV466
-1FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L
-+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhAAC
-gYATsU4dSb5vvYkuhnLJPYpiHOEOagLSwwggm8CD4JqA8CC/lzIJBI3LkR7Ve1Mw
-xYiDbQQPaxGsdCxaDuE+rOHmJcCNxum4gIYxeOOGHLa9eezTXLu2s0kBgsWx3I0U
-98lI4E+gRHiU27NXlNiEKvVq3GhzWvKdUqClbtLZ+67gzqN3MHUwHwYDVR0jBBgw
-FoAUsjZ7PCKVgcZLkxE8xaWJ8cf5jmowMwYDVR0RBCwwKoIWYWx0ZXJuYXRlLm5h
-bWUub25lLmNvbYIQYW5vdGhlci5uYW1lLmNvbTAdBgNVHQ4EFgQUas7dEjv/R3ig
-GcCdPRLL5P3HPU8wCwYHKoZIzjgEAwUAAy8AMCwCFFuvuEosI+5a+lSmpEahvhyE
-31WUAhR6+NkSdChlT0v6HmjyhBL1hLZYNA==
------END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/server-wc-private-key.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/server-wc-private-key.pem b/tests/python/proton_tests/ssl_db/server-wc-private-key.pem
deleted file mode 100644
index c4556fb..0000000
--- a/tests/python/proton_tests/ssl_db/server-wc-private-key.pem
+++ /dev/null
@@ -1,15 +0,0 @@
-Bag Attributes
-    friendlyName: server-wc-certificate
-    localKeyID: 54 69 6D 65 20 31 35 30 31 37 31 30 38 31 38 34 39 33 
-Key Attributes: <No Attributes>
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIBljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIFt9KwMYb/OQCAggA
-MBQGCCqGSIb3DQMHBAjQ+Hr462sAigSCAVAmqByfn+Ujb9TfpEI0d6mlW7Nyko00
-chzSFz61RVA/twfbLImhYvEo7P+UglcqGc1H3DaysDuMjbiNqgP25lDHO6ndhN7r
-XaeNshI8U3RQfUrhTwcA2pGpHQ6t+TGNKifRuJMbcHxWDNr+Tdod8uUADZt8Ywb+
-WQOqIrByNJryx5i2yZT7FphYrz6N0L5cNKVIirNv9/FOlKiyuzzg5c4NmABkpajE
-ZyT2H1p/qFipz8XeQ7BvFVDWSGn6Jb8vRvcc/swoCNSs8Wukr7tbryie2IbgktES
-gw7mVOw/Wdw6u26Q8Dz1c+eyy1WPuCiubFKUK12Ul0X9KKYCufVvQPoQBsMGikRM
-JcvrMd1cZ60pANJhnrogE6VEYE3NQrPC6SNao0NB+g4CW3tOH6m80H5+yHrMdvjo
-MQNXdlwdNWrCEH6hXJxzuE1qM5Ajc82bfwo=
------END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/server-wc-request.pem
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/server-wc-request.pem b/tests/python/proton_tests/ssl_db/server-wc-request.pem
deleted file mode 100644
index af867f2..0000000
--- a/tests/python/proton_tests/ssl_db/server-wc-request.pem
+++ /dev/null
@@ -1,16 +0,0 @@
------BEGIN NEW CERTIFICATE REQUEST-----
-MIICmTCCAlcCAQAwMDEdMBsGA1UEAwwUKi5wcmVmaXgqLmRvbWFpbi5jb20xDzAN
-BgNVBAoTBlNlcnZlcjCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLf
-Spwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4Ad
-NG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQT
-WhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGB
-APfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0
-SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEk
-O8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GEAAKBgBOxTh1Jvm+9
-iS6Gcsk9imIc4Q5qAtLDCCCbwIPgmoDwIL+XMgkEjcuRHtV7UzDFiINtBA9rEax0
-LFoO4T6s4eYlwI3G6biAhjF444Yctr157NNcu7azSQGCxbHcjRT3yUjgT6BEeJTb
-s1eU2IQq9WrcaHNa8p1SoKVu0tn7ruDOoGUwYwYJKoZIhvcNAQkOMVYwVDAzBgNV
-HREELDAqghZhbHRlcm5hdGUubmFtZS5vbmUuY29tghBhbm90aGVyLm5hbWUuY29t
-MB0GA1UdDgQWBBRqzt0SO/9HeKAZwJ09Esvk/cc9TzALBgcqhkjOOAQDBQADLwAw
-LAIUNn3ravBNvEsgZRjQd4EPPvQ1k9wCFEuakAyAzmt2ZfIKX3ZmTIgNKsvy
------END NEW CERTIFICATE REQUEST-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/server-wc.pkcs12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/server-wc.pkcs12 b/tests/python/proton_tests/ssl_db/server-wc.pkcs12
deleted file mode 100644
index 0ceccbc..0000000
Binary files a/tests/python/proton_tests/ssl_db/server-wc.pkcs12 and /dev/null differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/tests/python/proton_tests/ssl_db/server.pkcs12
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/ssl_db/server.pkcs12 b/tests/python/proton_tests/ssl_db/server.pkcs12
deleted file mode 100644
index f3c19e2..0000000
Binary files a/tests/python/proton_tests/ssl_db/server.pkcs12 and /dev/null differ


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[10/11] qpid-proton git commit: PROTON-1885: [python] move tests/python to python/tests

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/engine.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/engine.py b/python/tests/proton_tests/engine.py
new file mode 100644
index 0000000..d4f5a5d
--- /dev/null
+++ b/python/tests/proton_tests/engine.py
@@ -0,0 +1,2714 @@
+#
+# 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.
+#
+from __future__ import absolute_import
+
+import os, gc
+import sys
+from . import common
+from time import time, sleep
+from proton import *
+from .common import pump, Skipped
+from proton.reactor import Reactor
+
+
+# older versions of gc do not provide the garbage list
+if not hasattr(gc, "garbage"):
+  gc.garbage=[]
+
+# future test areas
+#  + different permutations of setup
+#   - creating deliveries and calling input/output before opening the session/link
+#  + shrinking output_size down to something small? should the engine buffer?
+#  + resuming
+#    - locally and remotely created deliveries with the same tag
+
+# Jython 2.5 needs this:
+try:
+    bytes()
+except:
+    bytes = str
+
+# and this...
+try:
+    bytearray()
+except:
+    def bytearray(x):
+        return b'\x00' * x
+
+OUTPUT_SIZE = 10*1024
+
+class Test(common.Test):
+
+  def __init__(self, *args):
+    common.Test.__init__(self, *args)
+    self._wires = []
+
+  def connection(self):
+    c1 = Connection()
+    c2 = Connection()
+    t1 = Transport()
+    t1.bind(c1)
+    t2 = Transport()
+    t2.bind(c2)
+    self._wires.append((c1, t1, c2, t2))
+
+    mask1 = 0
+    mask2 = 0
+
+    for cat in ("TRACE_FRM", "TRACE_RAW"):
+      trc = os.environ.get("PN_%s" % cat)
+      if trc and trc.lower() in ("1", "2", "yes", "true"):
+        mask1 = mask1 | getattr(Transport, cat)
+      if trc == "2":
+        mask2 = mask2 | getattr(Transport, cat)
+    t1.trace(mask1)
+    t2.trace(mask2)
+
+    return c1, c2
+
+  def link(self, name, max_frame=None, idle_timeout=None):
+    c1, c2 = self.connection()
+    if max_frame:
+      c1.transport.max_frame_size = max_frame[0]
+      c2.transport.max_frame_size = max_frame[1]
+    if idle_timeout:
+      # idle_timeout in seconds expressed as float
+      c1.transport.idle_timeout = idle_timeout[0]
+      c2.transport.idle_timeout = idle_timeout[1]
+    c1.open()
+    c2.open()
+    ssn1 = c1.session()
+    ssn1.open()
+    self.pump()
+    ssn2 = c2.session_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
+    ssn2.open()
+    self.pump()
+    snd = ssn1.sender(name)
+    rcv = ssn2.receiver(name)
+    return snd, rcv
+
+  def cleanup(self):
+    self._wires = []
+
+  def pump(self, buffer_size=OUTPUT_SIZE):
+    for c1, t1, c2, t2 in self._wires:
+      pump(t1, t2, buffer_size)
+
+class ConnectionTest(Test):
+
+  def setUp(self):
+    gc.enable()
+    self.c1, self.c2 = self.connection()
+
+  def cleanup(self):
+    # release resources created by this class
+    super(ConnectionTest, self).cleanup()
+    self.c1 = None
+    self.c2 = None
+
+  def tearDown(self):
+    self.cleanup()
+    gc.collect()
+    assert not gc.garbage
+
+  def test_open_close(self):
+    assert self.c1.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+    assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+    self.c1.open()
+    self.pump()
+
+    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+    assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
+
+    self.c2.open()
+    self.pump()
+
+    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    self.c1.close()
+    self.pump()
+
+    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+    self.c2.close()
+    self.pump()
+
+    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+    assert self.c2.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+  def test_simultaneous_open_close(self):
+    assert self.c1.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+    assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+    self.c1.open()
+    self.c2.open()
+
+    self.pump()
+
+    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    self.c1.close()
+    self.c2.close()
+
+    self.pump()
+
+    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+    assert self.c2.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+  def test_capabilities(self):
+    self.c1.offered_capabilities = Array(UNDESCRIBED, Data.SYMBOL,
+                                         symbol("O_one"),
+                                         symbol("O_two"),
+                                         symbol("O_three"))
+
+    self.c1.desired_capabilities = Array(UNDESCRIBED, Data.SYMBOL,
+                                         symbol("D_one"),
+                                         symbol("D_two"),
+                                         symbol("D_three"))
+    self.c1.open()
+
+    assert self.c2.remote_offered_capabilities is None
+    assert self.c2.remote_desired_capabilities is None
+
+    self.pump()
+
+    assert self.c2.remote_offered_capabilities == self.c1.offered_capabilities, \
+        (self.c2.remote_offered_capabilities, self.c1.offered_capabilities)
+    assert self.c2.remote_desired_capabilities == self.c1.desired_capabilities, \
+        (self.c2.remote_desired_capabilities, self.c1.desired_capabilities)
+
+  def test_condition(self):
+    self.c1.open()
+    self.c2.open()
+    self.pump()
+    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
+    self.c1.condition = cond
+    self.c1.close()
+
+    self.pump()
+
+    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+    rcond = self.c2.remote_condition
+    assert rcond == cond, (rcond, cond)
+
+  def test_properties(self, p1={symbol("key"): symbol("value")}, p2=None):
+    self.c1.properties = p1
+    self.c2.properties = p2
+    self.c1.open()
+    self.c2.open()
+    self.pump()
+
+    assert self.c2.remote_properties == p1, (self.c2.remote_properties, p1)
+    assert self.c1.remote_properties == p2, (self.c2.remote_properties, p2)
+
+  # The proton implementation limits channel_max to 32767.
+  # If I set the application's limit lower than that, I should
+  # get my wish.  If I set it higher -- not.
+  def test_channel_max_low(self, value=1234):
+    self.c1.transport.channel_max = value
+    self.c1.open()
+    self.pump()
+    assert self.c1.transport.channel_max == value, (self.c1.transport.channel_max, value)
+
+  def test_channel_max_high(self, value=65535):
+    self.c1.transport.channel_max = value
+    self.c1.open()
+    self.pump()
+    assert self.c1.transport.channel_max == 32767, (self.c1.transport.channel_max, value)
+
+  def test_channel_max_raise_and_lower(self):
+    upper_limit = 32767
+
+    # It's OK to lower the max below upper_limit.
+    self.c1.transport.channel_max = 12345
+    assert self.c1.transport.channel_max == 12345
+
+    # But it won't let us raise the limit above PN_IMPL_CHANNEL_MAX.
+    self.c1.transport.channel_max = 65535
+    assert self.c1.transport.channel_max == upper_limit
+
+    # send the OPEN frame
+    self.c1.open()
+    self.pump()
+
+    # Now it's too late to make any change, because
+    # we have already sent the OPEN frame.
+    try:
+      self.c1.transport.channel_max = 666
+      assert False, "expected session exception"
+    except:
+      pass
+
+    assert self.c1.transport.channel_max == upper_limit
+
+
+  # TODO: Currently failing test - PROTON-1759 - skip
+  def test_channel_max_limits_sessions(self):
+    raise Skipped('Test fails - PROTON-1759')
+    # This is an index -- so max number of channels should be 1.
+    self.c1.transport.channel_max = 0
+    self.c1.open()
+    self.c2.open()
+    ssn_0 = self.c2.session()
+    assert ssn_0 != None
+    ssn_0.open()
+    self.pump()
+    try:
+      ssn_1 = self.c2.session()
+      ssn_1.open()
+      self.pump()
+      assert False, "expected session exception"
+    except SessionException:
+      pass
+
+  def test_cleanup(self):
+    self.c1.open()
+    self.c2.open()
+    self.pump()
+    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    t1 = self.c1.transport
+    t2 = self.c2.transport
+    c2 = self.c2
+    self.c1.close()
+    # release all references to C1, except that held by the transport
+    self.cleanup()
+    gc.collect()
+    # transport should flush last state from C1:
+    pump(t1, t2)
+    assert c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+  def test_user_config(self):
+    self.c1.user = "vindaloo"
+    self.c1.password = "secret"
+    self.c1.open()
+    self.pump()
+
+    self.c2.user = "leela"
+    self.c2.password = "trustno1"
+    self.c2.open()
+    self.pump()
+
+    assert self.c1.user == "vindaloo", self.c1.user
+    assert self.c1.password == None, self.c1.password
+    assert self.c2.user == "leela", self.c2.user
+    assert self.c2.password == None, self.c2.password
+
+class SessionTest(Test):
+
+  def setUp(self):
+    gc.enable()
+    self.c1, self.c2 = self.connection()
+    self.ssn = self.c1.session()
+    self.c1.open()
+    self.c2.open()
+
+  def cleanup(self):
+    # release resources created by this class
+    super(SessionTest, self).cleanup()
+    self.c1 = None
+    self.c2 = None
+    self.ssn = None
+
+  def tearDown(self):
+    self.cleanup()
+    gc.collect()
+    assert not gc.garbage
+
+  def test_open_close(self):
+    assert self.ssn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+    self.ssn.open()
+
+    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+
+    self.pump()
+
+    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+
+    ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
+
+    assert ssn != None
+    assert ssn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
+    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+
+    ssn.open()
+
+    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+
+    self.pump()
+
+    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    ssn.close()
+
+    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    self.pump()
+
+    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+    self.ssn.close()
+
+    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+    self.pump()
+
+    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+  def test_simultaneous_close(self):
+    self.ssn.open()
+    self.pump()
+    ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
+    assert ssn != None
+    ssn.open()
+    self.pump()
+
+    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    self.ssn.close()
+    ssn.close()
+
+    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+
+    self.pump()
+
+    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+  def test_closing_connection(self):
+    self.ssn.open()
+    self.pump()
+    self.c1.close()
+    self.pump()
+    self.ssn.close()
+    self.pump()
+
+  def test_condition(self):
+    self.ssn.open()
+    self.pump()
+    ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
+    assert ssn != None
+    ssn.open()
+    self.pump()
+
+    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
+    self.ssn.condition = cond
+    self.ssn.close()
+
+    self.pump()
+
+    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+    rcond = ssn.remote_condition
+    assert rcond == cond, (rcond, cond)
+
+  def test_cleanup(self):
+    snd, rcv = self.link("test-link")
+    snd.open()
+    rcv.open()
+    self.pump()
+    snd_ssn = snd.session
+    rcv_ssn = rcv.session
+    assert rcv_ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    self.ssn = None
+    snd_ssn.close()
+    snd_ssn.free()
+    del snd_ssn
+    gc.collect()
+    self.pump()
+    assert rcv_ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+  def test_reopen_on_same_session_without_free(self):
+    """
+    confirm that a link is correctly opened when attaching to a previously
+    closed link *that has not been freed yet* on the same session
+    """
+    self.ssn.open()
+    self.pump()
+
+    ssn2 = self.c2.session_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
+    ssn2.open()
+    self.pump()
+    snd = self.ssn.sender("test-link")
+    rcv = ssn2.receiver("test-link")
+
+    assert snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+    assert rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+    snd.open()
+    rcv.open()
+    self.pump()
+
+    assert snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    snd.close()
+    rcv.close()
+    self.pump()
+
+    assert snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+    assert rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+    snd = self.ssn.sender("test-link")
+    rcv = ssn2.receiver("test-link")
+    assert snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+    assert rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+    snd.open()
+    rcv.open()
+    self.pump()
+
+    assert snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+  def test_set_get_outgoing_window(self):
+    assert self.ssn.outgoing_window == 2147483647
+
+    self.ssn.outgoing_window = 1024
+    assert self.ssn.outgoing_window == 1024
+
+
+class LinkTest(Test):
+
+  def setUp(self):
+    gc.enable()
+    self.snd, self.rcv = self.link("test-link")
+
+  def cleanup(self):
+    # release resources created by this class
+    super(LinkTest, self).cleanup()
+    self.snd = None
+    self.rcv = None
+
+  def tearDown(self):
+    self.cleanup()
+    gc.collect()
+    assert not gc.garbage, gc.garbage
+
+  def test_open_close(self):
+    assert self.snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+    self.snd.open()
+
+    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+    self.pump()
+
+    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
+
+    self.rcv.open()
+
+    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    self.pump()
+
+    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    self.snd.close()
+
+    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    self.pump()
+
+    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+    self.rcv.close()
+
+    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+    self.pump()
+
+    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+  def test_simultaneous_open_close(self):
+    assert self.snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+    self.snd.open()
+    self.rcv.open()
+
+    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+
+    self.pump()
+
+    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    self.snd.close()
+    self.rcv.close()
+
+    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+
+    self.pump()
+
+    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+  def test_multiple(self):
+    rcv = self.snd.session.receiver("second-rcv")
+    assert rcv.name == "second-rcv"
+    self.snd.open()
+    rcv.open()
+    self.pump()
+    c2 = self.rcv.session.connection
+    l = c2.link_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
+    while l:
+      l.open()
+      l = l.next(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
+    self.pump()
+
+    assert self.snd
+    assert rcv
+    self.snd.close()
+    rcv.close()
+    ssn = rcv.session
+    conn = ssn.connection
+    ssn.close()
+    conn.close()
+    self.pump()
+
+  def test_closing_session(self):
+    self.snd.open()
+    self.rcv.open()
+    ssn1 = self.snd.session
+    self.pump()
+    ssn1.close()
+    self.pump()
+    self.snd.close()
+    self.pump()
+
+  def test_closing_connection(self):
+    self.snd.open()
+    self.rcv.open()
+    ssn1 = self.snd.session
+    c1 = ssn1.connection
+    self.pump()
+    c1.close()
+    self.pump()
+    self.snd.close()
+    self.pump()
+
+  def assertEqualTermini(self, t1, t2):
+    assert t1.type == t2.type, (t1.type, t2.type)
+    assert t1.address == t2.address, (t1.address, t2.address)
+    assert t1.durability == t2.durability, (t1.durability, t2.durability)
+    assert t1.expiry_policy == t2.expiry_policy, (t1.expiry_policy, t2.expiry_policy)
+    assert t1.timeout == t2.timeout, (t1.timeout, t2.timeout)
+    assert t1.dynamic == t2.dynamic, (t1.dynamic, t2.dynamic)
+    for attr in ["properties", "capabilities", "outcomes", "filter"]:
+      d1 = getattr(t1, attr)
+      d2 = getattr(t2, attr)
+      assert d1.format() == d2.format(), (attr, d1.format(), d2.format())
+
+  def _test_source_target(self, config_source, config_target):
+    if config_source is None:
+      self.snd.source.type = Terminus.UNSPECIFIED
+    else:
+      config_source(self.snd.source)
+    if config_target is None:
+      self.snd.target.type = Terminus.UNSPECIFIED
+    else:
+      config_target(self.snd.target)
+    self.snd.open()
+    self.pump()
+    self.assertEqualTermini(self.rcv.remote_source, self.snd.source)
+    self.assertEqualTermini(self.rcv.remote_target, self.snd.target)
+    self.rcv.target.copy(self.rcv.remote_target)
+    self.rcv.source.copy(self.rcv.remote_source)
+    self.rcv.open()
+    self.pump()
+    self.assertEqualTermini(self.snd.remote_target, self.snd.target)
+    self.assertEqualTermini(self.snd.remote_source, self.snd.source)
+
+  def test_source_target(self):
+    self._test_source_target(TerminusConfig(address="source"),
+                             TerminusConfig(address="target"))
+
+  def test_source(self):
+    self._test_source_target(TerminusConfig(address="source"), None)
+
+  def test_target(self):
+    self._test_source_target(None, TerminusConfig(address="target"))
+
+  def test_coordinator(self):
+    self._test_source_target(None, TerminusConfig(type=Terminus.COORDINATOR))
+
+  def test_source_target_full(self):
+    self._test_source_target(TerminusConfig(address="source",
+                                            timeout=3,
+                                            dist_mode=Terminus.DIST_MODE_MOVE,
+                                            filter=[("int", 1), ("symbol", "two"), ("string", "three")],
+                                            capabilities=["one", "two", "three"]),
+                             TerminusConfig(address="source",
+                                            timeout=7,
+                                            capabilities=[]))
+  def test_distribution_mode(self):
+    self._test_source_target(TerminusConfig(address="source",
+                                            dist_mode=Terminus.DIST_MODE_COPY),
+                             TerminusConfig(address="target"))
+    assert self.rcv.remote_source.distribution_mode == Terminus.DIST_MODE_COPY
+    assert self.rcv.remote_target.distribution_mode == Terminus.DIST_MODE_UNSPECIFIED
+
+  def test_dynamic_link(self):
+    self._test_source_target(TerminusConfig(address=None, dynamic=True), None)
+    assert self.rcv.remote_source.dynamic
+    assert self.rcv.remote_source.address is None
+
+  def test_condition(self):
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+
+    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
+    self.snd.condition = cond
+    self.snd.close()
+
+    self.pump()
+
+    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+    rcond = self.rcv.remote_condition
+    assert rcond == cond, (rcond, cond)
+
+  def test_settle_mode(self):
+    self.snd.snd_settle_mode = Link.SND_UNSETTLED
+    assert self.snd.snd_settle_mode == Link.SND_UNSETTLED
+    self.rcv.rcv_settle_mode = Link.RCV_SECOND
+    assert self.rcv.rcv_settle_mode == Link.RCV_SECOND
+
+    assert self.snd.remote_rcv_settle_mode != Link.RCV_SECOND
+    assert self.rcv.remote_snd_settle_mode != Link.SND_UNSETTLED
+
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+
+    assert self.snd.remote_rcv_settle_mode == Link.RCV_SECOND
+    assert self.rcv.remote_snd_settle_mode == Link.SND_UNSETTLED
+
+  def test_max_message_size(self):
+    assert self.snd.max_message_size == 0
+    assert self.rcv.remote_max_message_size == 0
+    self.snd.max_message_size = 13579
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+    assert self.rcv.remote_max_message_size == 13579
+
+  def test_cleanup(self):
+    snd, rcv = self.link("test-link")
+    snd.open()
+    rcv.open()
+    self.pump()
+    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+    snd.close()
+    snd.free()
+    del snd
+    gc.collect()
+    self.pump()
+    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+class TerminusConfig:
+
+  def __init__(self, type=None, address=None, timeout=None, durability=None,
+               filter=None, capabilities=None, dynamic=False, dist_mode=None):
+    self.address = address
+    self.timeout = timeout
+    self.durability = durability
+    self.filter = filter
+    self.capabilities = capabilities
+    self.dynamic = dynamic
+    self.dist_mode = dist_mode
+    self.type = type
+
+  def __call__(self, terminus):
+    if self.type is not None:
+      terminus.type = self.type
+    if self.address is not None:
+      terminus.address = self.address
+    if self.timeout is not None:
+      terminus.timeout = self.timeout
+    if self.durability is not None:
+      terminus.durability = self.durability
+    if self.capabilities is not None:
+      terminus.capabilities.put_array(False, Data.SYMBOL)
+      terminus.capabilities.enter()
+      for c in self.capabilities:
+        terminus.capabilities.put_symbol(c)
+    if self.filter is not None:
+      terminus.filter.put_map()
+      terminus.filter.enter()
+      for (t, v) in self.filter:
+        setter = getattr(terminus.filter, "put_%s" % t)
+        setter(v)
+    if self.dynamic:
+      terminus.dynamic = True
+    if self.dist_mode is not None:
+      terminus.distribution_mode = self.dist_mode
+
+class TransferTest(Test):
+
+  def setUp(self):
+    gc.enable()
+    self.snd, self.rcv = self.link("test-link")
+    self.c1 = self.snd.session.connection
+    self.c2 = self.rcv.session.connection
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+
+  def cleanup(self):
+    # release resources created by this class
+    super(TransferTest, self).cleanup()
+    self.c1 = None
+    self.c2 = None
+    self.snd = None
+    self.rcv = None
+
+  def tearDown(self):
+    self.cleanup()
+    gc.collect()
+    assert not gc.garbage
+
+  def test_work_queue(self):
+    assert self.c1.work_head is None
+    self.snd.delivery("tag")
+    assert self.c1.work_head is None
+    self.rcv.flow(1)
+    self.pump()
+    d = self.c1.work_head
+    assert d is not None
+    tag = d.tag
+    assert tag == "tag", tag
+    assert d.writable
+
+    n = self.snd.send(b"this is a test")
+    assert self.snd.advance()
+    assert self.c1.work_head is None
+
+    self.pump()
+
+    d = self.c2.work_head
+    assert d.tag == "tag"
+    assert d.readable
+
+  def test_multiframe(self):
+    self.rcv.flow(1)
+    self.snd.delivery("tag")
+    msg = b"this is a test"
+    n = self.snd.send(msg)
+    assert n == len(msg)
+
+    self.pump()
+
+    d = self.rcv.current
+    assert d
+    assert d.tag == "tag", repr(d.tag)
+    assert d.readable
+
+    binary = self.rcv.recv(1024)
+    assert binary == msg, (binary, msg)
+
+    binary = self.rcv.recv(1024)
+    assert binary == b""
+
+    msg = b"this is more"
+    n = self.snd.send(msg)
+    assert n == len(msg)
+    assert self.snd.advance()
+
+    self.pump()
+
+    binary = self.rcv.recv(1024)
+    assert binary == msg, (binary, msg)
+
+    binary = self.rcv.recv(1024)
+    assert binary is None
+
+  def test_disposition(self):
+    self.rcv.flow(1)
+
+    self.pump()
+
+    sd = self.snd.delivery("tag")
+    msg = b"this is a test"
+    n = self.snd.send(msg)
+    assert n == len(msg)
+    assert self.snd.advance()
+
+    self.pump()
+
+    rd = self.rcv.current
+    assert rd is not None
+    assert rd.tag == sd.tag
+    rmsg = self.rcv.recv(1024)
+    assert rmsg == msg
+    rd.update(Delivery.ACCEPTED)
+
+    self.pump()
+
+    rdisp = sd.remote_state
+    ldisp = rd.local_state
+    assert rdisp == ldisp == Delivery.ACCEPTED, (rdisp, ldisp)
+    assert sd.updated
+
+    sd.update(Delivery.ACCEPTED)
+
+    self.pump()
+
+    assert sd.local_state == rd.remote_state == Delivery.ACCEPTED
+    sd.settle()
+
+  def test_delivery_id_ordering(self):
+    self.rcv.flow(1024)
+    self.pump(buffer_size=64*1024)
+
+    #fill up delivery buffer on sender
+    for m in range(1024):
+      sd = self.snd.delivery("tag%s" % m)
+      msg = ("message %s" % m).encode('ascii')
+      n = self.snd.send(msg)
+      assert n == len(msg)
+      assert self.snd.advance()
+
+    self.pump(buffer_size=64*1024)
+
+    #receive a session-windows worth of messages and accept them
+    for m in range(1024):
+      rd = self.rcv.current
+      assert rd is not None, m
+      assert rd.tag == ("tag%s" % m), (rd.tag, m)
+      msg = self.rcv.recv(1024)
+      assert msg == ("message %s" % m).encode('ascii'), (msg, m)
+      rd.update(Delivery.ACCEPTED)
+      rd.settle()
+
+    self.pump(buffer_size=64*1024)
+
+    #add some new deliveries
+    for m in range(1024, 1450):
+      sd = self.snd.delivery("tag%s" % m)
+      msg = ("message %s" % m).encode('ascii')
+      n = self.snd.send(msg)
+      assert n == len(msg)
+      assert self.snd.advance()
+
+    #handle all disposition changes to sent messages
+    d = self.c1.work_head
+    while d:
+      next_d = d.work_next
+      if d.updated:
+        d.update(Delivery.ACCEPTED)
+        d.settle()
+      d = next_d
+
+    #submit some more deliveries
+    for m in range(1450, 1500):
+      sd = self.snd.delivery("tag%s" % m)
+      msg = ("message %s" % m).encode('ascii')
+      n = self.snd.send(msg)
+      assert n == len(msg)
+      assert self.snd.advance()
+
+    self.pump(buffer_size=64*1024)
+    self.rcv.flow(1024)
+    self.pump(buffer_size=64*1024)
+
+    #verify remaining messages can be received and accepted
+    for m in range(1024, 1500):
+      rd = self.rcv.current
+      assert rd is not None, m
+      assert rd.tag == ("tag%s" % m), (rd.tag, m)
+      msg = self.rcv.recv(1024)
+      assert msg == ("message %s" % m).encode('ascii'), (msg, m)
+      rd.update(Delivery.ACCEPTED)
+      rd.settle()
+
+  def test_cleanup(self):
+    self.rcv.flow(10)
+    self.pump()
+
+    for x in range(10):
+        self.snd.delivery("tag%d" % x)
+        msg = b"this is a test"
+        n = self.snd.send(msg)
+        assert n == len(msg)
+        assert self.snd.advance()
+    self.snd.close()
+    self.snd.free()
+    self.snd = None
+    gc.collect()
+
+    self.pump()
+
+    for x in range(10):
+        rd = self.rcv.current
+        assert rd is not None
+        assert rd.tag == "tag%d" % x
+        rmsg = self.rcv.recv(1024)
+        assert self.rcv.advance()
+        assert rmsg == msg
+        # close of snd should've settled:
+        assert rd.settled
+        rd.settle()
+
+class MaxFrameTransferTest(Test):
+
+  def setUp(self):
+    pass
+
+  def cleanup(self):
+    # release resources created by this class
+    super(MaxFrameTransferTest, self).cleanup()
+    self.c1 = None
+    self.c2 = None
+    self.snd = None
+    self.rcv = None
+
+  def tearDown(self):
+    self.cleanup()
+
+  def message(self, size):
+    parts = []
+    for i in range(size):
+      parts.append(str(i))
+    return "/".join(parts)[:size].encode("utf-8")
+
+  def testMinFrame(self):
+    """
+    Configure receiver to support minimum max-frame as defined by AMQP-1.0.
+    Verify transfer of messages larger than 512.
+    """
+    self.snd, self.rcv = self.link("test-link", max_frame=[0,512])
+    self.c1 = self.snd.session.connection
+    self.c2 = self.rcv.session.connection
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+    assert self.rcv.session.connection.transport.max_frame_size == 512
+    assert self.snd.session.connection.transport.remote_max_frame_size == 512
+
+    self.rcv.flow(1)
+    self.snd.delivery("tag")
+    msg = self.message(513)
+    n = self.snd.send(msg)
+    assert n == len(msg)
+    assert self.snd.advance()
+
+    self.pump()
+
+    binary = self.rcv.recv(513)
+    assert binary == msg
+
+    binary = self.rcv.recv(1024)
+    assert binary == None
+
+  def testOddFrame(self):
+    """
+    Test an odd sized max limit with data that will require multiple frames to
+    be transfered.
+    """
+    self.snd, self.rcv = self.link("test-link", max_frame=[0,521])
+    self.c1 = self.snd.session.connection
+    self.c2 = self.rcv.session.connection
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+    assert self.rcv.session.connection.transport.max_frame_size == 521
+    assert self.snd.session.connection.transport.remote_max_frame_size == 521
+
+    self.rcv.flow(2)
+    self.snd.delivery("tag")
+    msg = ("X" * 1699).encode('utf-8')
+    n = self.snd.send(msg)
+    assert n == len(msg)
+    assert self.snd.advance()
+
+    self.pump()
+
+    binary = self.rcv.recv(1699)
+    assert binary == msg
+
+    binary = self.rcv.recv(1024)
+    assert binary == None
+
+    self.rcv.advance()
+
+    self.snd.delivery("gat")
+    msg = self.message(1426)
+    n = self.snd.send(msg)
+    assert n == len(msg)
+    assert self.snd.advance()
+
+    self.pump()
+
+    binary = self.rcv.recv(1426)
+    assert binary == msg
+
+    self.pump()
+
+    binary = self.rcv.recv(1024)
+    assert binary == None
+
+  def testSendQueuedMultiFrameMessages(self, sendSingleFrameMsg = False):
+    """
+    Test that multiple queued messages on the same link
+    with multi-frame content are sent correctly. Use an
+    odd max frame size, send enough data to use many.
+    """
+    self.snd, self.rcv = self.link("test-link", max_frame=[0,517])
+    self.c1 = self.snd.session.connection
+    self.c2 = self.rcv.session.connection
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+    assert self.rcv.session.connection.transport.max_frame_size == 517
+    assert self.snd.session.connection.transport.remote_max_frame_size == 517
+
+    self.rcv.flow(5)
+
+    self.pump()
+
+    # Send a delivery with 5 frames, all bytes as X1234
+    self.snd.delivery("tag")
+    msg = ("X1234" * 425).encode('utf-8')
+    assert 2125 == len(msg)
+    n = self.snd.send(msg)
+    assert n == len(msg)
+    assert self.snd.advance()
+
+    # Send a delivery with 5 frames, all bytes as Y5678
+    self.snd.delivery("tag2")
+    msg2 = ("Y5678" * 425).encode('utf-8')
+    assert 2125 == len(msg2)
+    n = self.snd.send(msg2)
+    assert n == len(msg2)
+    assert self.snd.advance()
+
+    self.pump()
+
+    if sendSingleFrameMsg:
+        # Send a delivery with 1 frame
+        self.snd.delivery("tag3")
+        msg3 = ("Z").encode('utf-8')
+        assert 1 == len(msg3)
+        n = self.snd.send(msg3)
+        assert n == len(msg3)
+        assert self.snd.advance()
+        self.pump()
+
+    binary = self.rcv.recv(5000)
+    self.assertEqual(binary, msg)
+
+    self.rcv.advance()
+
+    binary2 = self.rcv.recv(5000)
+    self.assertEqual(binary2, msg2)
+
+    self.rcv.advance()
+
+    if sendSingleFrameMsg:
+        binary3 = self.rcv.recv(5000)
+        self.assertEqual(binary3, msg3)
+        self.rcv.advance()
+
+    self.pump()
+
+  def testSendQueuedMultiFrameMessagesThenSingleFrameMessage(self):
+    self.testSendQueuedMultiFrameMessages(sendSingleFrameMsg = True)
+
+  def testBigMessage(self):
+    """
+    Test transferring a big message.
+    """
+    self.snd, self.rcv = self.link("test-link")
+    self.c1 = self.snd.session.connection
+    self.c2 = self.rcv.session.connection
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+
+    self.rcv.flow(2)
+    self.snd.delivery("tag")
+    msg = self.message(1024*256)
+    n = self.snd.send(msg)
+    assert n == len(msg)
+    assert self.snd.advance()
+
+    self.pump()
+
+    binary = self.rcv.recv(1024*256)
+    assert binary == msg
+
+    binary = self.rcv.recv(1024)
+    assert binary == None
+
+
+class IdleTimeoutTest(Test):
+
+  def setUp(self):
+    pass
+
+  def cleanup(self):
+    # release resources created by this class
+    super(IdleTimeoutTest, self).cleanup()
+    self.snd = None
+    self.rcv = None
+    self.c1 = None
+    self.c2 = None
+
+  def tearDown(self):
+    self.cleanup()
+
+  def message(self, size):
+    parts = []
+    for i in range(size):
+      parts.append(str(i))
+    return "/".join(parts)[:size]
+
+  def testGetSet(self):
+    """
+    Verify the configuration and negotiation of the idle timeout.
+    """
+
+    self.snd, self.rcv = self.link("test-link", idle_timeout=[1.0,2.0])
+    self.c1 = self.snd.session.connection
+    self.c2 = self.rcv.session.connection
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+    # proton advertises 1/2 the configured timeout to the peer:
+    assert self.rcv.session.connection.transport.idle_timeout == 2.0
+    assert self.rcv.session.connection.transport.remote_idle_timeout == 0.5
+    assert self.snd.session.connection.transport.idle_timeout == 1.0
+    assert self.snd.session.connection.transport.remote_idle_timeout == 1.0
+
+  def testTimeout(self):
+    """
+    Verify the AMQP Connection idle timeout.
+    """
+
+    # snd will timeout the Connection if no frame is received within 1000 ticks
+    self.snd, self.rcv = self.link("test-link", idle_timeout=[1.0,0])
+    self.c1 = self.snd.session.connection
+    self.c2 = self.rcv.session.connection
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+
+    t_snd = self.snd.session.connection.transport
+    t_rcv = self.rcv.session.connection.transport
+    assert t_rcv.idle_timeout == 0.0
+    # proton advertises 1/2 the timeout (see spec)
+    assert t_rcv.remote_idle_timeout == 0.5
+    assert t_snd.idle_timeout == 1.0
+    assert t_snd.remote_idle_timeout == 0.0
+
+    sndr_frames_in = t_snd.frames_input
+    rcvr_frames_out = t_rcv.frames_output
+
+    # at t+1msec, nothing should happen:
+    clock = 0.001
+    assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
+    assert t_rcv.tick(clock) == 0.251,  "deadline to send keepalive"
+    self.pump()
+    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
+
+    # at one tick from expected idle frame send, nothing should happen:
+    clock = 0.250
+    assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
+    assert t_rcv.tick(clock) == 0.251,  "deadline to send keepalive"
+    self.pump()
+    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
+
+    # this should cause rcvr to expire and send a keepalive
+    clock = 0.251
+    assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
+    assert t_rcv.tick(clock) == 0.501, "deadline to send keepalive"
+    self.pump()
+    sndr_frames_in += 1
+    rcvr_frames_out += 1
+    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
+    assert rcvr_frames_out == t_rcv.frames_output, "unexpected frame"
+
+    # since a keepalive was received, sndr will rebase its clock against this tick:
+    # and the receiver should not change its deadline
+    clock = 0.498
+    assert t_snd.tick(clock) == 1.498, "deadline for remote timeout"
+    assert t_rcv.tick(clock) == 0.501, "deadline to send keepalive"
+    self.pump()
+    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
+
+    # now expire sndr
+    clock = 1.499
+    t_snd.tick(clock)
+    self.pump()
+    assert self.c2.state & Endpoint.REMOTE_CLOSED
+    assert self.c2.remote_condition.name == "amqp:resource-limit-exceeded"
+
+class CreditTest(Test):
+
+  def setUp(self):
+    self.snd, self.rcv = self.link("test-link", max_frame=(16*1024, 16*1024))
+    self.c1 = self.snd.session.connection
+    self.c2 = self.rcv.session.connection
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+
+  def cleanup(self):
+    # release resources created by this class
+    super(CreditTest, self).cleanup()
+    self.c1 = None
+    self.snd = None
+    self.c2 = None
+    self.rcv2 = None
+    self.snd2 = None
+
+  def tearDown(self):
+    self.cleanup()
+
+  def testCreditSender(self, count=1024):
+    credit = self.snd.credit
+    assert credit == 0, credit
+    self.rcv.flow(10)
+    self.pump()
+    credit = self.snd.credit
+    assert credit == 10, credit
+
+    self.rcv.flow(count)
+    self.pump()
+    credit = self.snd.credit
+    assert credit == 10 + count, credit
+
+  def testCreditReceiver(self):
+    self.rcv.flow(10)
+    self.pump()
+    assert self.rcv.credit == 10, self.rcv.credit
+
+    d = self.snd.delivery("tag")
+    assert d
+    assert self.snd.advance()
+    self.pump()
+    assert self.rcv.credit == 10, self.rcv.credit
+    assert self.rcv.queued == 1, self.rcv.queued
+    c = self.rcv.current
+    assert c.tag == "tag", c.tag
+    assert self.rcv.advance()
+    assert self.rcv.credit == 9, self.rcv.credit
+    assert self.rcv.queued == 0, self.rcv.queued
+
+  def _testBufferingOnClose(self, a, b):
+    for i in range(10):
+      d = self.snd.delivery("tag-%s" % i)
+      assert d
+      d.settle()
+    self.pump()
+    assert self.snd.queued == 10
+
+    endpoints = {"connection": (self.c1, self.c2),
+                 "session": (self.snd.session, self.rcv.session),
+                 "link": (self.snd, self.rcv)}
+
+    local_a, remote_a = endpoints[a]
+    local_b, remote_b = endpoints[b]
+
+    remote_b.close()
+    self.pump()
+    assert local_b.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+    local_a.close()
+    self.pump()
+    assert remote_a.state & Endpoint.REMOTE_CLOSED
+    assert self.snd.queued == 10
+
+  def testBufferingOnCloseLinkLink(self):
+    self._testBufferingOnClose("link", "link")
+
+  def testBufferingOnCloseLinkSession(self):
+    self._testBufferingOnClose("link", "session")
+
+  def testBufferingOnCloseLinkConnection(self):
+    self._testBufferingOnClose("link", "connection")
+
+  def testBufferingOnCloseSessionLink(self):
+    self._testBufferingOnClose("session", "link")
+
+  def testBufferingOnCloseSessionSession(self):
+    self._testBufferingOnClose("session", "session")
+
+  def testBufferingOnCloseSessionConnection(self):
+    self._testBufferingOnClose("session", "connection")
+
+  def testBufferingOnCloseConnectionLink(self):
+    self._testBufferingOnClose("connection", "link")
+
+  def testBufferingOnCloseConnectionSession(self):
+    self._testBufferingOnClose("connection", "session")
+
+  def testBufferingOnCloseConnectionConnection(self):
+    self._testBufferingOnClose("connection", "connection")
+
+  def testFullDrain(self):
+    assert self.rcv.credit == 0
+    assert self.snd.credit == 0
+    self.rcv.drain(10)
+    assert self.rcv.draining()
+    assert self.rcv.credit == 10
+    assert self.snd.credit == 0
+    self.pump()
+    assert self.rcv.credit == 10
+    assert self.snd.credit == 10
+    assert self.rcv.draining()
+    self.snd.drained()
+    assert self.rcv.credit == 10
+    assert self.snd.credit == 0
+    assert self.rcv.draining()
+    self.pump()
+    assert self.rcv.credit == 0
+    assert self.snd.credit == 0
+    assert not self.rcv.draining()
+    drained = self.rcv.drained()
+    assert drained == 10, drained
+
+  def testPartialDrain(self):
+    self.rcv.drain(2)
+    assert self.rcv.draining()
+    self.pump()
+
+    d = self.snd.delivery("tag")
+    assert d
+    assert self.snd.advance()
+    self.snd.drained()
+    assert self.rcv.draining()
+    self.pump()
+    assert not self.rcv.draining()
+
+    c = self.rcv.current
+    assert self.rcv.queued == 1, self.rcv.queued
+    assert c.tag == d.tag, c.tag
+    assert self.rcv.advance()
+    assert not self.rcv.current
+    assert self.rcv.credit == 0, self.rcv.credit
+    assert not self.rcv.draining()
+    drained = self.rcv.drained()
+    assert drained == 1, drained
+
+  def testDrainFlow(self):
+    assert self.rcv.credit == 0
+    assert self.snd.credit == 0
+    self.rcv.drain(10)
+    assert self.rcv.credit == 10
+    assert self.snd.credit == 0
+    self.pump()
+    assert self.rcv.credit == 10
+    assert self.snd.credit == 10
+    self.snd.drained()
+    assert self.rcv.credit == 10
+    assert self.snd.credit == 0
+    self.pump()
+    assert self.rcv.credit == 0
+    assert self.snd.credit == 0
+    self.rcv.flow(10)
+    assert self.rcv.credit == 10
+    assert self.snd.credit == 0
+    self.pump()
+    assert self.rcv.credit == 10
+    assert self.snd.credit == 10
+    self.snd.drained()
+    assert self.rcv.credit == 10
+    assert self.snd.credit == 10
+    self.pump()
+    assert self.rcv.credit == 10
+    assert self.snd.credit == 10
+    drained = self.rcv.drained()
+    assert drained == 10, drained
+
+  def testNegative(self):
+    assert self.snd.credit == 0
+    d = self.snd.delivery("tag")
+    assert d
+    assert self.snd.advance()
+    self.pump()
+
+    assert self.rcv.credit == 0
+    assert self.rcv.queued == 0
+
+    self.rcv.flow(1)
+    assert self.rcv.credit == 1
+    assert self.rcv.queued == 0
+    self.pump()
+    assert self.rcv.credit == 1
+    assert self.rcv.queued == 1, self.rcv.queued
+
+    c = self.rcv.current
+    assert c
+    assert c.tag == "tag"
+    assert self.rcv.advance()
+    assert self.rcv.credit == 0
+    assert self.rcv.queued == 0
+
+  def testDrainZero(self):
+    assert self.snd.credit == 0
+    assert self.rcv.credit == 0
+    assert self.rcv.queued == 0
+    drained = self.rcv.drained()
+    assert drained == 0
+
+    self.rcv.flow(10)
+    self.pump()
+    assert self.snd.credit == 10
+    assert self.rcv.credit == 10
+    assert self.rcv.queued == 0
+
+    self.snd.drained()
+    self.pump()
+    assert self.snd.credit == 10
+    assert self.rcv.credit == 10
+    assert self.rcv.queued == 0
+    drained = self.rcv.drained()
+    assert drained == 0
+
+    self.rcv.drain(0)
+    assert self.snd.credit == 10
+    assert self.rcv.credit == 10
+    assert self.rcv.queued == 0
+
+    self.pump()
+
+    assert self.snd.credit == 10
+    assert self.rcv.credit == 10
+    assert self.rcv.queued == 0
+
+    self.snd.drained()
+    assert self.snd.credit == 0
+    assert self.rcv.credit == 10
+    assert self.rcv.queued == 0
+    drained = self.rcv.drained()
+    assert drained == 0
+    self.pump()
+
+    assert self.snd.credit == 0
+    assert self.rcv.credit == 0
+    assert self.rcv.queued == 0
+    drained = self.rcv.drained()
+    assert drained == 10
+
+
+  def testDrainOrder(self):
+    """ Verify drain/drained works regardless of ordering.  See PROTON-401
+    """
+    assert self.snd.credit == 0
+    assert self.rcv.credit == 0
+    assert self.rcv.queued == 0
+
+    #self.rcv.session.connection.transport.trace(Transport.TRACE_FRM)
+    #self.snd.session.connection.transport.trace(Transport.TRACE_FRM)
+
+    ## verify that a sender that has reached the drain state will respond
+    ## promptly to a drain issued by the peer.
+    self.rcv.flow(10)
+    self.pump()
+    assert self.snd.credit == 10, self.snd.credit
+    assert self.rcv.credit == 10, self.rcv.credit
+
+    sd = self.snd.delivery("tagA")
+    assert sd
+    n = self.snd.send(b"A")
+    assert n == 1
+    self.pump()
+    self.snd.advance()
+
+    # done sending, so signal that we are drained:
+    self.snd.drained()
+    self.pump()
+    assert self.snd.credit == 9, self.snd.credit
+    assert self.rcv.credit == 10, self.rcv.credit
+
+    self.rcv.drain(0)
+    self.pump()
+    assert self.snd.credit == 9, self.snd.credit
+    assert self.rcv.credit == 10, self.rcv.credit
+
+    data = self.rcv.recv(10)
+    assert data == b"A", data
+    self.rcv.advance()
+    self.pump()
+    assert self.snd.credit == 9, self.snd.credit
+    assert self.rcv.credit == 9, self.rcv.credit
+
+    self.snd.drained()
+    self.pump()
+    assert self.snd.credit == 0, self.snd.credit
+    assert self.rcv.credit == 0, self.rcv.credit
+
+    # verify that a drain requested by the peer is not "acknowledged" until
+    # after the sender has completed sending its pending messages
+
+    self.rcv.flow(10)
+    self.pump()
+    assert self.snd.credit == 10, self.snd.credit
+    assert self.rcv.credit == 10, self.rcv.credit
+
+    sd = self.snd.delivery("tagB")
+    assert sd
+    n = self.snd.send(b"B")
+    assert n == 1
+    self.snd.advance()
+    self.pump()
+    assert self.snd.credit == 9, self.snd.credit
+    assert self.rcv.credit == 10, self.rcv.credit
+
+    self.rcv.drain(0)
+    self.pump()
+    assert self.snd.credit == 9, self.snd.credit
+    assert self.rcv.credit == 10, self.rcv.credit
+
+    sd = self.snd.delivery("tagC")
+    assert sd
+    n = self.snd.send(b"C")
+    assert n == 1
+    self.snd.advance()
+    self.pump()
+    assert self.snd.credit == 8, self.snd.credit
+    assert self.rcv.credit == 10, self.rcv.credit
+
+    # now that the sender has finished sending everything, it can signal
+    # drained
+    self.snd.drained()
+    self.pump()
+    assert self.snd.credit == 0, self.snd.credit
+    assert self.rcv.credit == 2, self.rcv.credit
+
+    data = self.rcv.recv(10)
+    assert data == b"B", data
+    self.rcv.advance()
+    data = self.rcv.recv(10)
+    assert data == b"C", data
+    self.rcv.advance()
+    self.pump()
+    assert self.snd.credit == 0, self.snd.credit
+    assert self.rcv.credit == 0, self.rcv.credit
+
+
+  def testPushback(self, count=10):
+    assert self.snd.credit == 0
+    assert self.rcv.credit == 0
+
+    self.rcv.flow(count)
+    self.pump()
+
+    for i in range(count):
+      d = self.snd.delivery("tag%s" % i)
+      assert d
+      self.snd.advance()
+
+    assert self.snd.queued == count
+    assert self.rcv.queued == 0
+    self.pump()
+    assert self.snd.queued == 0
+    assert self.rcv.queued == count
+
+    d = self.snd.delivery("extra")
+    self.snd.advance()
+
+    assert self.snd.queued == 1
+    assert self.rcv.queued == count
+    self.pump()
+    assert self.snd.queued == 1
+    assert self.rcv.queued == count
+
+  def testHeadOfLineBlocking(self):
+      self.snd2 = self.snd.session.sender("link-2")
+      self.rcv2 = self.rcv.session.receiver("link-2")
+      self.snd2.open()
+      self.rcv2.open()
+      self.pump()
+      assert self.snd2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+      assert self.rcv2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+      self.rcv.flow(5)
+      self.rcv2.flow(10)
+      self.pump()
+
+      assert self.snd.credit == 5
+      assert self.snd2.credit == 10
+
+      for i in range(10):
+          tag = "test %d" % i
+          self.snd.delivery( tag )
+          self.snd.send( tag.encode("ascii") )
+          assert self.snd.advance()
+          self.snd2.delivery( tag )
+          self.snd2.send( tag.encode("ascii") )
+          assert self.snd2.advance()
+
+      self.pump()
+
+      for i in range(5):
+          b = self.rcv.recv( 512 )
+          assert self.rcv.advance()
+          b = self.rcv2.recv( 512 )
+          assert self.rcv2.advance()
+
+      for i in range(5):
+          b = self.rcv2.recv( 512 )
+          assert self.rcv2.advance()
+
+
+
+class SessionCreditTest(Test):
+
+  def tearDown(self):
+    self.cleanup()
+
+  def testBuffering(self, count=32, size=1024, capacity=16*1024, max_frame=1024):
+    snd, rcv = self.link("test-link", max_frame=(max_frame, max_frame))
+    rcv.session.incoming_capacity = capacity
+    snd.open()
+    rcv.open()
+    rcv.flow(count)
+    self.pump()
+
+    assert count > 0
+
+    total_bytes = count * size
+
+    assert snd.session.outgoing_bytes == 0, snd.session.outgoing_bytes
+    assert rcv.session.incoming_bytes == 0, rcv.session.incoming_bytes
+    assert snd.queued == 0, snd.queued
+    assert rcv.queued == 0, rcv.queued
+
+    data = bytes(bytearray(size))
+    idx = 0
+    while snd.credit:
+      d = snd.delivery("tag%s" % idx)
+      assert d
+      n = snd.send(data)
+      assert n == size, (n, size)
+      assert snd.advance()
+      self.pump()
+      idx += 1
+
+    assert idx == count, (idx, count)
+
+    assert snd.session.outgoing_bytes < total_bytes, (snd.session.outgoing_bytes, total_bytes)
+    assert rcv.session.incoming_bytes < capacity, (rcv.session.incoming_bytes, capacity)
+    assert snd.session.outgoing_bytes + rcv.session.incoming_bytes == total_bytes, \
+        (snd.session.outgoing_bytes, rcv.session.incoming_bytes, total_bytes)
+    if snd.session.outgoing_bytes > 0:
+      available = rcv.session.incoming_capacity - rcv.session.incoming_bytes
+      assert available < max_frame, (available, max_frame)
+
+    for i in range(count):
+      d = rcv.current
+      assert d, i
+      pending = d.pending
+      before = rcv.session.incoming_bytes
+      assert rcv.advance()
+      after = rcv.session.incoming_bytes
+      assert before - after == pending, (before, after, pending)
+      snd_before = snd.session.incoming_bytes
+      self.pump()
+      snd_after = snd.session.incoming_bytes
+
+      assert rcv.session.incoming_bytes < capacity
+      if snd_before > 0:
+        assert capacity - after <= max_frame
+        assert snd_before > snd_after
+      if snd_after > 0:
+        available = rcv.session.incoming_capacity - rcv.session.incoming_bytes
+        assert available < max_frame, available
+
+  def testBufferingSize16(self):
+    self.testBuffering(size=16)
+
+  def testBufferingSize256(self):
+    self.testBuffering(size=256)
+
+  def testBufferingSize512(self):
+    self.testBuffering(size=512)
+
+  def testBufferingSize2048(self):
+    self.testBuffering(size=2048)
+
+  def testBufferingSize1025(self):
+    self.testBuffering(size=1025)
+
+  def testBufferingSize1023(self):
+    self.testBuffering(size=1023)
+
+  def testBufferingSize989(self):
+    self.testBuffering(size=989)
+
+  def testBufferingSize1059(self):
+    self.testBuffering(size=1059)
+
+  def testCreditWithBuffering(self):
+    snd, rcv = self.link("test-link", max_frame=(1024, 1024))
+    rcv.session.incoming_capacity = 64*1024
+    snd.open()
+    rcv.open()
+    rcv.flow(128)
+    self.pump()
+
+    assert snd.credit == 128, snd.credit
+    assert rcv.queued == 0, rcv.queued
+
+    idx = 0
+    while snd.credit:
+      d = snd.delivery("tag%s" % idx)
+      snd.send(("x"*1024).encode('ascii'))
+      assert d
+      assert snd.advance()
+      self.pump()
+      idx += 1
+
+    assert idx == 128, idx
+    assert rcv.queued < 128, rcv.queued
+
+    rcv.flow(1)
+    self.pump()
+    assert snd.credit == 1, snd.credit
+
+class SettlementTest(Test):
+
+  def setUp(self):
+    self.snd, self.rcv = self.link("test-link")
+    self.c1 = self.snd.session.connection
+    self.c2 = self.rcv.session.connection
+    self.snd.open()
+    self.rcv.open()
+    self.pump()
+
+  def cleanup(self):
+    # release resources created by this class
+    super(SettlementTest, self).cleanup()
+    self.c1 = None
+    self.snd = None
+    self.c2 = None
+    self.rcv2 = None
+    self.snd2 = None
+
+  def tearDown(self):
+    self.cleanup()
+
+  def testSettleCurrent(self):
+    self.rcv.flow(10)
+    self.pump()
+
+    assert self.snd.credit == 10, self.snd.credit
+    d = self.snd.delivery("tag")
+    e = self.snd.delivery("tag2")
+    assert d
+    assert e
+    c = self.snd.current
+    assert c.tag == "tag", c.tag
+    c.settle()
+    c = self.snd.current
+    assert c.tag == "tag2", c.tag
+    c.settle()
+    c = self.snd.current
+    assert not c
+    self.pump()
+
+    c = self.rcv.current
+    assert c
+    assert c.tag == "tag", c.tag
+    assert c.settled
+    c.settle()
+    c = self.rcv.current
+    assert c
+    assert c.tag == "tag2", c.tag
+    assert c.settled
+    c.settle()
+    c = self.rcv.current
+    assert not c
+
+  def testUnsettled(self):
+    self.rcv.flow(10)
+    self.pump()
+
+    assert self.snd.unsettled == 0, self.snd.unsettled
+    assert self.rcv.unsettled == 0, self.rcv.unsettled
+
+    d = self.snd.delivery("tag")
+    assert d
+    assert self.snd.unsettled == 1, self.snd.unsettled
+    assert self.rcv.unsettled == 0, self.rcv.unsettled
+    assert self.snd.advance()
+    self.pump()
+
+    assert self.snd.unsettled == 1, self.snd.unsettled
+    assert self.rcv.unsettled == 1, self.rcv.unsettled
+
+    c = self.rcv.current
+    assert c
+    c.settle()
+
+    assert self.snd.unsettled == 1, self.snd.unsettled
+    assert self.rcv.unsettled == 0, self.rcv.unsettled
+
+  def testMultipleUnsettled(self, count=1024, size=1024):
+    self.rcv.flow(count)
+    self.pump()
+
+    assert self.snd.unsettled == 0, self.snd.unsettled
+    assert self.rcv.unsettled == 0, self.rcv.unsettled
+
+    unsettled = []
+
+    for i in range(count):
+      sd = self.snd.delivery("tag%s" % i)
+      assert sd
+      n = self.snd.send(("x"*size).encode('ascii'))
+      assert n == size, n
+      assert self.snd.advance()
+      self.pump()
+
+      rd = self.rcv.current
+      assert rd, "did not receive delivery %s" % i
+      n = rd.pending
+      b = self.rcv.recv(n)
+      assert len(b) == n, (b, n)
+      rd.update(Delivery.ACCEPTED)
+      assert self.rcv.advance()
+      self.pump()
+      unsettled.append(rd)
+
+    assert self.rcv.unsettled == count
+
+    for rd in unsettled:
+      rd.settle()
+
+  def testMultipleUnsettled2K1K(self):
+    self.testMultipleUnsettled(2048, 1024)
+
+  def testMultipleUnsettled4K1K(self):
+    self.testMultipleUnsettled(4096, 1024)
+
+  def testMultipleUnsettled1K2K(self):
+    self.testMultipleUnsettled(1024, 2048)
+
+  def testMultipleUnsettled2K2K(self):
+    self.testMultipleUnsettled(2048, 2048)
+
+  def testMultipleUnsettled4K2K(self):
+    self.testMultipleUnsettled(4096, 2048)
+
+class PipelineTest(Test):
+
+  def setUp(self):
+    self.c1, self.c2 = self.connection()
+
+  def cleanup(self):
+    # release resources created by this class
+    super(PipelineTest, self).cleanup()
+    self.c1 = None
+    self.c2 = None
+
+  def tearDown(self):
+    self.cleanup()
+
+  def test(self):
+    ssn = self.c1.session()
+    snd = ssn.sender("sender")
+    self.c1.open()
+    ssn.open()
+    snd.open()
+
+    for i in range(10):
+      t = "delivery-%s" % i
+      d = snd.delivery(t)
+      snd.send(t.encode('ascii'))
+      d.settle()
+
+    snd.close()
+    ssn.close()
+    self.c1.close()
+
+    self.pump()
+
+    state = self.c2.state
+    assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
+    ssn2 = self.c2.session_head(Endpoint.LOCAL_UNINIT)
+    assert ssn2
+    state == ssn2.state
+    assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
+    rcv = self.c2.link_head(Endpoint.LOCAL_UNINIT)
+    assert rcv
+    state = rcv.state
+    assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
+
+    self.c2.open()
+    ssn2.open()
+    rcv.open()
+    rcv.flow(10)
+    assert rcv.queued == 0, rcv.queued
+
+    self.pump()
+
+    assert rcv.queued == 10, rcv.queued
+    state = rcv.state
+    assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
+    state = ssn2.state
+    assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
+    state = self.c2.state
+    assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
+
+    for i in range(rcv.queued):
+      d = rcv.current
+      assert d
+      assert d.tag == "delivery-%s" % i
+      d.settle()
+
+    assert rcv.queued == 0, rcv.queued
+
+
+class ServerTest(Test):
+
+  def testKeepalive(self):
+    """ Verify that idle frames are sent to keep a Connection alive
+    """
+    idle_timeout = self.delay
+    server = common.TestServer()
+    server.start()
+
+    class Program:
+
+      def on_reactor_init(self, event):
+        self.conn = event.reactor.connection()
+        self.conn.hostname = "%s:%s" % (server.host, server.port)
+        self.conn.open()
+        self.old_count = None
+        event.reactor.schedule(3 * idle_timeout, self)
+
+      def on_connection_bound(self, event):
+        event.transport.idle_timeout = idle_timeout
+
+      def on_connection_remote_open(self, event):
+        self.old_count = event.transport.frames_input
+
+      def on_timer_task(self, event):
+        assert self.conn.state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE), "Connection terminated"
+        assert self.conn.transport.frames_input > self.old_count, "No idle frames received"
+        self.conn.close()
+
+    Reactor(Program()).run()
+    server.stop()
+
+  def testIdleTimeout(self):
+    """ Verify that a Connection is terminated properly when Idle frames do not
+    arrive in a timely manner.
+    """
+    idle_timeout = self.delay
+    server = common.TestServer(idle_timeout=idle_timeout)
+    server.start()
+
+    class Program:
+
+      def on_reactor_init(self, event):
+        self.conn = event.reactor.connection()
+        self.conn.hostname = "%s:%s" % (server.host, server.port)
+        self.conn.open()
+        self.remote_condition = None
+        self.old_count = None
+        # verify the connection stays up even if we don't explicitly send stuff
+        # wait up to 3x the idle timeout
+        event.reactor.schedule(3 * idle_timeout, self)
+
+      def on_connection_bound(self, event):
+        self.transport = event.transport
+
+      def on_connection_remote_open(self, event):
+        self.old_count = event.transport.frames_output
+
+      def on_connection_remote_close(self, event):
+        assert self.conn.remote_condition
+        assert self.conn.remote_condition.name == "amqp:resource-limit-exceeded"
+        self.remote_condition = self.conn.remote_condition
+
+      def on_timer_task(self, event):
+        assert self.conn.state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE), "Connection terminated"
+        assert self.conn.transport.frames_output > self.old_count, "No idle frames sent"
+
+        # now wait to explicitly cause the other side to expire:
+        suspend_time = 3 * idle_timeout
+        if os.name=="nt":
+          # On windows, the full delay gets too close to the graceful/hard close tipping point
+          suspend_time = 2.5 * idle_timeout
+        sleep(suspend_time)
+
+    p = Program()
+    Reactor(p).run()
+    assert p.remote_condition
+    assert p.remote_condition.name == "amqp:resource-limit-exceeded"
+    server.stop()
+
+class NoValue:
+
+  def __init__(self):
+    pass
+
+  def apply(self, dlv):
+    pass
+
+  def check(self, dlv):
+    assert dlv.data == None
+    assert dlv.section_number == 0
+    assert dlv.section_offset == 0
+    assert dlv.condition == None
+    assert dlv.failed == False
+    assert dlv.undeliverable == False
+    assert dlv.annotations == None
+
+class RejectValue:
+  def __init__(self, condition):
+    self.condition = condition
+
+  def apply(self, dlv):
+    dlv.condition = self.condition
+
+  def check(self, dlv):
+    assert dlv.data == None, dlv.data
+    assert dlv.section_number == 0
+    assert dlv.section_offset == 0
+    assert dlv.condition == self.condition, (dlv.condition, self.condition)
+    assert dlv.failed == False
+    assert dlv.undeliverable == False
+    assert dlv.annotations == None
+
+class ReceivedValue:
+  def __init__(self, section_number, section_offset):
+    self.section_number = section_number
+    self.section_offset = section_offset
+
+  def apply(self, dlv):
+    dlv.section_number = self.section_number
+    dlv.section_offset = self.section_offset
+
+  def check(self, dlv):
+    assert dlv.data == None, dlv.data
+    assert dlv.section_number == self.section_number, (dlv.section_number, self.section_number)
+    assert dlv.section_offset == self.section_offset
+    assert dlv.condition == None
+    assert dlv.failed == False
+    assert dlv.undeliverable == False
+    assert dlv.annotations == None
+
+class ModifiedValue:
+  def __init__(self, failed, undeliverable, annotations):
+    self.failed = failed
+    self.undeliverable = undeliverable
+    self.annotations = annotations
+
+  def apply(self, dlv):
+    dlv.failed = self.failed
+    dlv.undeliverable = self.undeliverable
+    dlv.annotations = self.annotations
+
+  def check(self, dlv):
+    assert dlv.data == None, dlv.data
+    assert dlv.section_number == 0
+    assert dlv.section_offset == 0
+    assert dlv.condition == None
+    assert dlv.failed == self.failed
+    assert dlv.undeliverable == self.undeliverable
+    assert dlv.annotations == self.annotations, (dlv.annotations, self.annotations)
+
+class CustomValue:
+  def __init__(self, data):
+    self.data = data
+
+  def apply(self, dlv):
+    dlv.data = self.data
+
+  def check(self, dlv):
+    assert dlv.data == self.data, (dlv.data, self.data)
+    assert dlv.section_number == 0
+    assert dlv.section_offset == 0
+    assert dlv.condition == None
+    assert dlv.failed == False
+    assert dlv.undeliverable == False
+    assert dlv.annotations == None
+
+class DeliveryTest(Test):
+
+  def tearDown(self):
+    self.cleanup()
+
+  def testDisposition(self, count=1, tag="tag%i", type=Delivery.ACCEPTED, value=NoValue()):
+    snd, rcv = self.link("test-link")
+    snd.open()
+    rcv.open()
+
+    snd_deliveries = []
+    for i in range(count):
+      d = snd.delivery(tag % i)
+      snd_deliveries.append(d)
+      snd.advance()
+
+    rcv.flow(count)
+    self.pump()
+
+    rcv_deliveries = []
+    for i in range(count):
+      d = rcv.current
+      assert d.tag == (tag % i)
+      rcv_deliveries.append(d)
+      rcv.advance()
+
+    for d in rcv_deliveries:
+      value.apply(d.local)
+      d.update(type)
+
+    self.pump()
+
+    for d in snd_deliveries:
+      assert d.remote_state == type
+      assert d.remote.type == type
+      value.check(d.remote)
+      value.apply(d.local)
+      d.update(type)
+
+    self.pump()
+
+    for d in rcv_deliveries:
+      assert d.remote_state == type
+      assert d.remote.type == type
+      value.check(d.remote)
+
+    for d in snd_deliveries:
+      d.settle()
+
+    self.pump()
+
+    for d in rcv_deliveries:
+      assert d.settled, d.settled
+      d.settle()
+
+  def testReceived(self):
+    self.testDisposition(type=Disposition.RECEIVED, value=ReceivedValue(1, 2))
+
+  def testRejected(self):
+    self.testDisposition(type=Disposition.REJECTED, value=RejectValue(Condition(symbol("foo"))))
+
+  def testReleased(self):
+    self.testDisposition(type=Disposition.RELEASED)
+
+  def testModified(self):
+    self.testDisposition(type=Disposition.MODIFIED,
+                         value=ModifiedValue(failed=True, undeliverable=True,
+                                             annotations={"key": "value"}))
+
+  def testCustom(self):
+    self.testDisposition(type=0x12345, value=CustomValue([1, 2, 3]))
+
+class CollectorTest(Test):
+
+  def setUp(self):
+    self.collector = Collector()
+
+  def drain(self):
+    result = []
+    while True:
+      e = self.collector.peek()
+      if e:
+        result.append(e)
+        self.collector.pop()
+      else:
+        break
+    return result
+
+  def expect(self, *types):
+    return self.expect_oneof(types)
+
+  def expect_oneof(self, *sequences):
+    events = self.drain()
+    types = tuple([e.type for e in events])
+
+    for alternative in sequences:
+      if types == alternative:
+        if len(events) == 1:
+          return events[0]
+        elif len(events) > 1:
+          return events
+        else:
+          return
+
+    assert False, "actual events %s did not match any of the expected sequences: %s" % (events, sequences)
+
+  def expect_until(self, *types):
+    events = self.drain()
+    etypes = tuple([e.type for e in events[-len(types):]])
+    assert etypes == types, "actual events %s did not end in expect sequence: %s" % (events, types)
+
+class EventTest(CollectorTest):
+
+  def tearDown(self):
+    self.cleanup()
+
+  def testEndpointEvents(self):
+    c1, c2 = self.connection()
+    c1.collect(self.collector)
+    self.expect(Event.CONNECTION_INIT)
+    self.pump()
+    self.expect()
+    c2.open()
+    self.pump()
+    self.expect(Event.CONNECTION_REMOTE_OPEN)
+    self.pump()
+    self.expect()
+
+    ssn = c2.session()
+    snd = ssn.sender("sender")
+    ssn.open()
+    snd.open()
+
+    self.expect()
+    self.pump()
+    self.expect(Event.SESSION_INIT, Event.SESSION_REMOTE_OPEN,
+                Event.LINK_INIT, Event.LINK_REMOTE_OPEN)
+
+    c1.open()
+    ssn2 = c1.session()
+    ssn2.open()
+    rcv = ssn2.receiver("receiver")
+    rcv.open()
+    self.pump()
+    self.expect(Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.SESSION_INIT, Event.SESSION_LOCAL_OPEN,
+                Event.TRANSPORT, Event.LINK_INIT, Event.LINK_LOCAL_OPEN,
+                Event.TRANSPORT)
+
+    rcv.close()
+    self.expect(Event.LINK_LOCAL_CLOSE, Event.TRANSPORT)
+    self.pump()
+    rcv.free()
+    del rcv
+    self.expect(Event.LINK_FINAL)
+    ssn2.free()
+    del ssn2
+    self.pump()
+    c1.free()
+    c1.transport.unbind()
+    self.expect_oneof((Event.SESSION_FINAL, Event.LINK_FINAL, Event.SESSION_FINAL,
+                       Event.CONNECTION_UNBOUND, Event.CONNECTION_FINAL),
+                      (Event.CONNECTION_UNBOUND, Event.SESSION_FINAL, Event.LINK_FINAL,
+                       Event.SESSION_FINAL, Event.CONNECTION_FINAL))
+
+  def testConnectionINIT_FINAL(self):
+    c = Connection()
+    c.collect(self.collector)
+    self.expect(Event.CONNECTION_INIT)
+    c.free()
+    self.expect(Event.CONNECTION_FINAL)
+
+  def testSessionINIT_FINAL(self):
+    c = Connection()
+    c.collect(self.collector)
+    self.expect(Event.CONNECTION_INIT)
+    s = c.session()
+    self.expect(Event.SESSION_INIT)
+    s.free()
+    self.expect(Event.SESSION_FINAL)
+    c.free()
+    self.expect(Event.CONNECTION_FINAL)
+
+  def testLinkINIT_FINAL(self):
+    c = Connection()
+    c.collect(self.collector)
+    self.expect(Event.CONNECTION_INIT)
+    s = c.session()
+    self.expect(Event.SESSION_INIT)
+    r = s.receiver("asdf")
+    self.expect(Event.LINK_INIT)
+    r.free()
+    self.expect(Event.LINK_FINAL)
+    c.free()
+    self.expect(Event.SESSION_FINAL, Event.CONNECTION_FINAL)
+
+  def testFlowEvents(self):
+    snd, rcv = self.link("test-link")
+    snd.session.connection.collect(self.collector)
+    rcv.open()
+    rcv.flow(10)
+    self.pump()
+    self.expect(Event.CONNECTION_INIT, Event.SESSION_INIT,
+                Event.LINK_INIT, Event.LINK_REMOTE_OPEN, Event.LINK_FLOW)
+    rcv.flow(10)
+    self.pump()
+    self.expect(Event.LINK_FLOW)
+    return snd, rcv
+
+  def testDeliveryEvents(self):
+    snd, rcv = self.link("test-link")
+    rcv.session.connection.collect(self.collector)
+    rcv.open()
+    rcv.flow(10)
+    self.pump()
+    self.expect(Event.CONNECTION_INIT, Event.SESSION_INIT,
+                Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
+    snd.delivery("delivery")
+    snd.send(b"Hello World!")
+    snd.advance()
+    self.pump()
+    self.expect()
+    snd.open()
+    self.pump()
+    self.expect(Event.LINK_REMOTE_OPEN, Event.DELIVERY)
+    rcv.session.connection.transport.unbind()
+    rcv.session.connection.free()
+    self.expect(Event.CONNECTION_UNBOUND, Event.TRANSPORT, Event.LINK_FINAL,
+                Event.SESSION_FINAL, Event.CONNECTION_FINAL)
+
+  def testDeliveryEventsDisp(self):
+    snd, rcv = self.testFlowEvents()
+    snd.open()
+    dlv = snd.delivery("delivery")
+    snd.send(b"Hello World!")
+    assert snd.advance()
+    self.expect(Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
+    self.pump()
+    self.expect(Event.LINK_FLOW)
+    rdlv = rcv.current
+    assert rdlv != None
+    assert rdlv.tag == "delivery"
+    rdlv.update(Delivery.ACCEPTED)
+    self.pump()
+    event = self.expect(Event.DELIVERY)
+    assert event.context == dlv, (dlv, event.context)
+
+  def testConnectionBOUND_UNBOUND(self):
+    c = Connection()
+    c.collect(self.collector)
+    self.expect(Event.CONNECTION_INIT)
+    t = Transport()
+    t.bind(c)
+    self.expect(Event.CONNECTION_BOUND)
+    t.unbind()
+    self.expect(Event.CONNECTION_UNBOUND, Event.TRANSPORT)
+
+  def testTransportERROR_CLOSE(self):
+    c = Connection()
+    c.collect(self.collector)
+    self.expect(Event.CONNECTION_INIT)
+    t = Transport()
+    t.bind(c)
+    self.expect(Event.CONNECTION_BOUND)
+    assert t.condition is None
+    t.push(b"asdf")
+    self.expect(Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED)
+    assert t.condition is not None
+    assert t.condition.name == "amqp:connection:framing-error"
+    assert "AMQP header mismatch" in t.condition.description
+    p = t.pending()
+    assert p > 0
+    t.pop(p)
+    self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+  def testTransportCLOSED(self):
+    c = Connection()
+    c.collect(self.collector)
+    self.expect(Event.CONNECTION_INIT)
+    t = Transport()
+    t.bind(c)
+    c.open()
+
+    self.expect(Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT)
+
+    c2 = Connection()
+    t2 = Transport()
+    t2.bind(c2)
+    c2.open()
+    c2.close()
+
+    pump(t, t2)
+
+    self.expect(Event.CONNECTION_REMOTE_OPEN, Event.CONNECTION_REMOTE_CLOSE,
+                Event.TRANSPORT_TAIL_CLOSED)
+
+    c.close()
+
+    pump(t, t2)
+
+    self.expect(Event.CONNECTION_LOCAL_CLOSE, Event.TRANSPORT,
+                Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+  def testLinkDetach(self):
+    c1 = Connection()
+    c1.collect(self.collector)
+    t1 = Transport()
+    t1.bind(c1)
+    c1.open()
+    s1 = c1.session()
+    s1.open()
+    l1 = s1.sender("asdf")
+    l1.open()
+    l1.detach()
+    self.expect_until(Event.LINK_LOCAL_DETACH, Event.TRANSPORT)
+
+    c2 = Connection()
+    c2.collect(self.collector)
+    t2 = Transport()
+    t2.bind(c2)
+
+    pump(t1, t2)
+
+    self.expect_until(Event.LINK_REMOTE_DETACH)
+
+class PeerTest(CollectorTest):
+
+  def setUp(self):
+    CollectorTest.setUp(self)
+    self.connection = Connection()
+    self.connection.collect(self.collector)
+    self.transport = Transport()
+    self.transport.bind(self.connection)
+    self.peer = Connection()
+    self.peer_transport = Transport()
+    self.peer_transport.bind(self.peer)
+    self.peer_transport.trace(Transport.TRACE_OFF)
+
+  def pump(self):
+    pump(self.transport, self.peer_transport)
+
+class TeardownLeakTest(PeerTest):
+
+  def doLeak(self, local, remote):
+    self.connection.open()
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT)
+
+    ssn = self.connection.session()
+    ssn.open()
+    self.expect(Event.SESSION_INIT, Event.SESSION_LOCAL_OPEN, Event.TRANSPORT)
+
+    snd = ssn.sender("sender")
+    snd.open()
+    self.expect(Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
+
+
+    self.pump()
+
+    self.peer.open()
+    self.peer.session_head(0).open()
+    self.peer.link_head(0).open()
+
+    self.pump()
+    self.expect_oneof((Event.CONNECTION_REMOTE_OPEN, Event.SESSION_REMOTE_OPEN,
+                       Event.LINK_REMOTE_OPEN, Event.LINK_FLOW),
+                      (Event.CONNECTION_REMOTE_OPEN, Event.SESSION_REMOTE_OPEN,
+                       Event.LINK_REMOTE_OPEN))
+
+    if local:
+      snd.close() # ha!!
+      self.expect(Event.LINK_LOCAL_CLOSE, Event.TRANSPORT)
+    ssn.close()
+    self.expect(Event.SESSION_LOCAL_CLOSE, Event.TRANSPORT)
+    self.connection.close()
+    self.expect(Event.CONNECTION_LOCAL_CLOSE, Event.TRANSPORT)
+
+    if remote:
+      self.peer.link_head(0).close() # ha!!
+    self.peer.session_head(0).close()
+    self.peer.close()
+
+    self.pump()
+
+    if remote:
+      self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.LINK_REMOTE_CLOSE,
+                  Event.SESSION_REMOTE_CLOSE, Event.CONNECTION_REMOTE_CLOSE,
+                  Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_CLOSED)
+    else:
+      self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.SESSION_REMOTE_CLOSE,
+                  Event.CONNECTION_REMOTE_CLOSE, Event.TRANSPORT_TAIL_CLOSED,
+                  Event.TRANSPORT_CLOSED)
+
+    self.connection.free()
+    self.expect(Event.LINK_FINAL, Event.SESSION_FINAL)
+    self.transport.unbind()
+
+    self.expect(Event.CONNECTION_UNBOUND, Event.CONNECTION_FINAL)
+
+  def testLocalRemoteLeak(self):
+    self.doLeak(True, True)
+
+  def testLocalLeak(self):
+    self.doLeak(True, False)
+
+  def testRemoteLeak(self):
+    self.doLeak(False, True)
+
+  def testLeak(self):
+    self.doLeak(False, False)
+
+class IdleTimeoutEventTest(PeerTest):
+
+  def half_pump(self):
+    p = self.transport.pending()
+    if p>0:
+      self.transport.pop(p)
+
+  def testTimeoutWithZombieServer(self, expectOpenCloseFrames=True):
+    self.transport.idle_timeout = self.delay
+    self.connection.open()
+    self.half_pump()
+    t = time()
+    self.transport.tick(t)
+    self.transport.tick(t + self.delay*4)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED)
+    assert self.transport.capacity() < 0
+    if expectOpenCloseFrames:
+      assert self.transport.pending() > 0
+    self.half_pump()
+    self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+    assert self.transport.pending() < 0
+
+  def testTimeoutWithZombieServerAndSASL(self):
+    sasl = self.transport.sasl()
+    self.testTimeoutWithZombieServer(expectOpenCloseFrames=False)
+
+class DeliverySegFaultTest(Test):
+
+  def testDeliveryAfterUnbind(self):
+    conn = Connection()
+    t = Transport()
+    ssn = conn.session()
+    snd = ssn.sender("sender")
+    dlv = snd.delivery("tag")
+    dlv.settle()
+    del dlv
+    t.bind(conn)
+    t.unbind()
+    dlv = snd.delivery("tag")
+
+class SaslEventTest(CollectorTest):
+
+  def testAnonymousNoInitialResponse(self):
+    conn = Connection()
+    conn.collect(self.collector)
+    transport = Transport(Transport.SERVER)
+    transport.bind(conn)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
+
+    transport.push(b'AMQP\x03\x01\x00\x00\x00\x00\x00 \x02\x01\x00\x00\x00SA'
+                   b'\xd0\x00\x00\x00\x10\x00\x00\x00\x02\xa3\tANONYMOUS@'
+                   b'AMQP\x00\x01\x00\x00')
+    self.expect(Event.TRANSPORT)
+    for i in range(1024):
+      p = transport.pending()
+      self.drain()
+    p = transport.pending()
+    self.expect()
+
+  def testPipelinedServerReadFirst(self):
+    conn = Connection()
+    conn.collect(self.collector)
+    transport = Transport(Transport.CLIENT)
+    s = transport.sasl()
+    s.allowed_mechs("ANONYMOUS PLAIN")
+    transport.bind(conn)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
+    transport.push(
+        # SASL
+        b'AMQP\x03\x01\x00\x00'
+        # @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:ANONYMOUS]]
+        b'\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS'
+        # @sasl-outcome(68) [code=0]
+        b'\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00'
+        # AMQP
+        b'AMQP\x00\x01\x00\x00'
+        )
+    self.expect(Event.TRANSPORT)
+    p = transport.pending()
+    bytes = transport.peek(p)
+    transport.pop(p)
+
+    server = Transport(Transport.SERVER)
+    server.push(bytes)
+    assert s.outcome == SASL.OK
+    assert server.sasl().outcome == SASL.OK
+
+  def testPipelinedServerWriteFirst(self):
+    conn = Connection()
+    conn.collect(self.collector)
+    transport = Transport(Transport.CLIENT)
+    s = transport.sasl()
+    s.allowed_mechs("ANONYMOUS")
+    transport.bind(conn)
+    p = transport.pending()
+    bytes = transport.peek(p)
+    transport.pop(p)
+    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
+    transport.push(
+        # SASL
+        b'AMQP\x03\x01\x00\x00'
+        # @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:ANONYMOUS]]
+        b'\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS'
+        # @sasl-outcome(68) [code=0]
+        b'\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00'
+        # AMQP
+        b'AMQP\x00\x01\x00\x00'
+        )
+    self.expect(Event.TRANSPORT)
+    p = transport.pending()
+    bytes = transport.peek(p)
+    transport.pop(p)
+    assert s.outcome == SASL.OK
+    # XXX: the bytes above appear to be correct, but we don't get any
+    # sort of event indicating that the transport is authenticated

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9778eda8/python/tests/proton_tests/handler.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/handler.py b/python/tests/proton_tests/handler.py
new file mode 100644
index 0000000..e239bb2
--- /dev/null
+++ b/python/tests/proton_tests/handler.py
@@ -0,0 +1,123 @@
+#
+# 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.
+#
+from __future__ import absolute_import
+
+import os, gc, traceback
+import sys
+from . import common
+from time import time, sleep
+from proton import *
+from .common import pump, Skipped
+from proton.reactor import Reactor
+
+
+CUSTOM = EventType("custom")
+
+class HandlerTest(common.Test):
+  def test_reactorHandlerCycling(self, n=0):
+
+    class CustomHandler(Handler):
+      UNSET = 999999999
+      def __init__(self):
+        self.offset = len(traceback.extract_stack())
+      def on_reactor_init(self, event):
+        self.depth = len(traceback.extract_stack())
+      def reset(self):
+        self.depth = self.UNSET
+      @property
+      def init_depth(self):
+        d = self.depth - self.offset
+        return d
+    custom = CustomHandler()
+
+    reactor = Reactor()
+    reactor.handler = custom
+    for i in range(n):
+      h = reactor.handler
+      reactor.handler = h
+    custom.reset()
+    reactor.run()
+    assert custom.init_depth < 50, "Unexpectedly long traceback for a simple handler"
+
+  def test_reactorHandlerCycling10k(self):
+    self.test_reactorHandlerCycling(10000)
+
+  def test_reactorHandlerCycling100(self):
+    self.test_reactorHandlerCycling(100)
+
+  def do_customEvent(self, reactor_handler, event_root):
+
+    class CustomHandler:
+      did_custom = False
+      did_init = False
+      def __init__(self, *handlers):
+        self.handlers = handlers
+      def on_reactor_init(self, event):
+        self.did_init = True
+      def on_custom(self, event):
+        self.did_custom = True
+
+    class CustomInvoker(CustomHandler):
+      def on_reactor_init(self, event):
+        h = event_root(event)
+        event.dispatch(h, CUSTOM)
+        self.did_init = True
+
+    child = CustomInvoker()
+    root = CustomHandler(child)
+
+    reactor = Reactor()
+
+    reactor_handler(reactor, root)
+    reactor.run()
+    assert root.did_init
+    assert child.did_init
+    assert root.did_custom
+    assert child.did_custom
+
+  def set_root(self, reactor, root):
+    reactor.handler = root
+  def add_root(self, reactor, root):
+    reactor.handler.add(root)
+  def append_root(self, reactor, root):
+    reactor.handler.handlers.append(root)
+
+  def event_root(self, event):
+    return event.root
+
+  def event_reactor_handler(self, event):
+    return event.reactor.handler
+
+  def test_set_handler(self):
+    self.do_customEvent(self.set_root, self.event_reactor_handler)
+
+  def test_add_handler(self):
+    self.do_customEvent(self.add_root, self.event_reactor_handler)
+
+  def test_append_handler(self):
+    self.do_customEvent(self.append_root, self.event_reactor_handler)
+
+  def test_set_root(self):
+    self.do_customEvent(self.set_root, self.event_root)
+
+  def test_add_root(self):
+    self.do_customEvent(self.add_root, self.event_root)
+
+  def test_append_root(self):
+    self.do_customEvent(self.append_root, self.event_root)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org