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 <acon...@redhat.com>
Authored: Wed Jul 4 15:43:16 2018 -0400
Committer: Alan Conway <acon...@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-unsubscr...@qpid.apache.org
For additional commands, e-mail: commits-h...@qpid.apache.org

Reply via email to