PROTON-1062: c++: Improved example test runner for connection_engine tests.
Fixes a test hang on windows. Monitor stdout to for 'ready' messages instead of testing ports: faster, more portable. Detect & raise broker errors, restart broker for remaining tests. Keep all process output for verificiation and error reporting. Clean up stray processes. Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/7b4fa65a Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/7b4fa65a Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/7b4fa65a Branch: refs/heads/master Commit: 7b4fa65a20da04ce32bd570b6552f7287adee665 Parents: 2bc4d25 Author: Alan Conway <[email protected]> Authored: Tue Jan 26 13:01:01 2016 -0500 Committer: Alan Conway <[email protected]> Committed: Wed Jan 27 16:55:07 2016 -0500 ---------------------------------------------------------------------- examples/cpp/CMakeLists.txt | 70 +++--- examples/cpp/broker.cpp | 4 +- examples/cpp/engine/CMakeLists.txt | 39 +--- examples/cpp/engine/example_test.py | 182 ---------------- examples/cpp/engine/helloworld.cpp | 1 - examples/cpp/example_test.py | 361 +++++++++++++++++++------------ examples/cpp/helloworld.cpp | 1 - examples/cpp/server.cpp | 4 +- 8 files changed, 268 insertions(+), 394 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b4fa65a/examples/cpp/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index 14d5748..4f6b742 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -21,43 +21,47 @@ find_package(ProtonCpp REQUIRED) include_directories(${ProtonCpp_INCLUDE_DIRS}) -set(examples - broker - helloworld - helloworld_direct - simple_recv - simple_send - direct_recv - direct_send - client - server - server_direct - recurring_timer - connection_options - queue_browser - selected_recv - ssl - ssl_client_cert - encode_decode) - -foreach(example ${examples}) +foreach(example + broker + helloworld + helloworld_direct + simple_recv + simple_send + direct_recv + direct_send + client + server + server_direct + recurring_timer + connection_options + queue_browser + selected_recv + ssl + ssl_client_cert + encode_decode) add_executable(${example} ${example}.cpp) target_link_libraries(${example} ${ProtonCpp_LIBRARIES}) set_source_files_properties(${example}.cpp PROPERTIES COMPILE_FLAGS "${CXX_WARNING_FLAGS}") endforeach() -set(env_py "${CMAKE_SOURCE_DIR}/proton-c/env.py") -set(test_bin_dir "$<TARGET_FILE_DIR:broker>") -if (WIN32) - # Ignore existing path (usualy containting spaces, escape chars). - # Choose just enough path for Windows, ';' separated. - set(test_path "${test_bin_dir}" "$<TARGET_FILE_DIR:qpid-proton>" "$<TARGET_FILE_DIR:qpid-proton-cpp>") -else(WIN32) - # ':' separated path with test_bin_dir first. - set(test_path "${test_bin_dir}:$ENV{PATH}") -endif(WIN32) +add_subdirectory(engine) -add_test(NAME cpp_example_test - COMMAND ${PYTHON_EXECUTABLE} ${env_py} -- "PATH=${test_path}" ${VALGRIND_ENV} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v) +set(env_py ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/proton-c/env.py) -add_subdirectory(engine) +function(set_test_path dir) + if (WIN32) + set(test_path "${dir}" "$<TARGET_FILE_DIR:qpid-proton>" "$<TARGET_FILE_DIR:qpid-proton-cpp>" PARENT_SCOPE) + else(WIN32) + set(test_path "${dir}:$ENV{PATH}" PARENT_SCOPE) + endif(WIN32) +endfunction() + +set_test_path("$<TARGET_FILE_DIR:broker>") + +add_test(NAME cpp_container_example_test + COMMAND ${env_py} -- "PATH=${test_path}" ${VALGRIND_ENV} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleTest) + +set_test_path("$<TARGET_FILE_DIR:engine-broker>") + +add_test(NAME cpp_engine_example_test + COMMAND ${env_py} -- "PATH=${test_path}" ${VALGRIND_ENV} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ConnectionEngineExampleTest) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b4fa65a/examples/cpp/broker.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp index 48efa93..ae42b20 100644 --- a/examples/cpp/broker.cpp +++ b/examples/cpp/broker.cpp @@ -62,10 +62,10 @@ int main(int argc, char **argv) { options opts(argc, argv); opts.add_value(url, 'a', "address", "listen on URL", "URL"); - + try { opts.parse(); - + broker b(url); proton::container(b.handler()).run(); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b4fa65a/examples/cpp/engine/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/cpp/engine/CMakeLists.txt b/examples/cpp/engine/CMakeLists.txt index ceecc2b..bafa20c 100644 --- a/examples/cpp/engine/CMakeLists.txt +++ b/examples/cpp/engine/CMakeLists.txt @@ -21,38 +21,17 @@ find_package(ProtonCpp REQUIRED) include_directories(${ProtonCpp_INCLUDE_DIRS}) -set(examples - broker - helloworld - simple_recv - simple_send - direct_recv - direct_send - client - server) - -foreach(example ${examples}) - set(extra_source "") - if (example EQUAL broker) - set(extra_source broker.hpp) - endif() +foreach(example + broker + helloworld + simple_recv + simple_send + direct_recv + direct_send + client + server) add_executable(engine-${example} ${example}.cpp ${extra_source}) target_link_libraries(engine-${example} ${ProtonCpp_LIBRARIES}) set_source_files_properties(engine-${example}.cpp PROPERTIES COMPILE_FLAGS "${CXX_WARNING_FLAGS}") set_target_properties(engine-${example} PROPERTIES OUTPUT_NAME ${example}) endforeach() - -set(env_py "${CMAKE_SOURCE_DIR}/proton-c/env.py") -set(test_bin_dir "$<TARGET_FILE_DIR:engine-broker>") - -if (WIN32) - # Ignore existing path (usualy containting spaces, escape chars). - # Choose just enough path for Windows, ';' separated. - set(test_path "${test_bin_dir}" "$<TARGET_FILE_DIR:qpid-proton>" "$<TARGET_FILE_DIR:qpid-proton-cpp>") -else(WIN32) - # ':' separated path with test_bin_dir first. - set(test_path "${test_bin_dir}:$ENV{PATH}") -endif(WIN32) - -add_test(NAME cpp_example_engine_test - COMMAND ${PYTHON_EXECUTABLE} ${env_py} -- "PATH=${test_path}" ${VALGRIND_ENV} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b4fa65a/examples/cpp/engine/example_test.py ---------------------------------------------------------------------- diff --git a/examples/cpp/engine/example_test.py b/examples/cpp/engine/example_test.py deleted file mode 100644 index a4c4c17..0000000 --- a/examples/cpp/engine/example_test.py +++ /dev/null @@ -1,182 +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 -# - -# This is a test script to run the examples and verify that they behave as expected. - -import unittest -import os, sys, socket, time -from random import randrange -from subprocess import Popen, PIPE, STDOUT -from copy import copy -import platform -from os.path import dirname as dirname - -def cmdline(*args): - """Adjust executable name args[0] for windows and/or valgrind""" - args = list(args) - if platform.system() == "Windows": - args[0] += ".exe" - if "VALGRIND" in os.environ and os.environ["VALGRIND"]: - args = [os.environ["VALGRIND"], "--error-exitcode=42", "--quiet", - "--leak-check=full"] + args - return args - -def background(*args): - """Run executable in the backround, return the popen""" - p = Popen(cmdline(*args), stdout=PIPE, stderr=sys.stderr) - p.args = args # Save arguments for debugging output - return p - -def verify(p): - """Wait for executable to exit and verify status.""" - try: - out, err = p.communicate() - except Exception as e: - raise Exception("Error running %s: %s", p.args, e) - if p.returncode: - raise Exception("""%s exit code %s -vvvvvvvvvvvvvvvv -%s -^^^^^^^^^^^^^^^^ -""" % (p.args, p.returncode, out)) - if platform.system() == "Windows": - # Just \n please - if out: - out = out.translate(None, '\r') - return out - -def execute(*args): - return verify(background(*args)) - -NULL = open(os.devnull, 'w') - -def wait_addr(addr, timeout=10): - """Wait up to timeout for something to listen on port""" - deadline = time.time() + timeout - while time.time() < deadline: - try: - c = socket.create_connection(addr.split(":"), deadline - time.time()) - c.close() - return - except socket.error as e: - time.sleep(0.01) - raise Exception("Timed out waiting for %s", addr) - -def pick_addr(): - """Pick a new host:port address.""" - # TODO aconway 2015-07-14: need a safer way to pick ports. - p = randrange(10000, 20000) - return "127.0.0.1:%s" % p - -def ssl_certs_dir(): - """Absolute path to the test SSL certificates""" - pn_root = dirname(dirname(dirname(sys.argv[0]))) - return os.path.join(pn_root, "examples/cpp/ssl_certs") - -class Broker(object): - """Run the test broker""" - - @classmethod - def get(cls): - if not hasattr(cls, "_broker"): - cls._broker = Broker() - return cls._broker - - @classmethod - def stop(cls): - if cls.get() and cls._broker.process: - cls._broker.process.kill() - cls._broker = None - - def __init__(self): - broker_exe = os.environ.get("TEST_BROKER") or "broker" - self.addr = pick_addr() - cmd = cmdline(broker_exe, "-a", self.addr) - try: - self.process = Popen(cmd, stdout=NULL, stderr=sys.stderr) - wait_addr(self.addr) - self.addr += "/examples" - except Exception as e: - raise Exception("Error running %s: %s", cmd, e) - -class ExampleTest(unittest.TestCase): - """Run the examples, verify they behave as expected.""" - - @classmethod - def tearDownClass(self): - Broker.stop() - - def test_helloworld(self): - b = Broker.get() - hw = execute("helloworld", b.addr) - self.assertEqual('Hello World!\n', hw) - - def test_simple_send_recv(self): - b = Broker.get() - send = execute("simple_send", "-a", b.addr) - self.assertEqual("all messages confirmed\n", send) - recv = execute("simple_recv", "-a", b.addr) - recv_expect = "simple_recv listening on amqp://%s\n" % (b.addr) - recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)]) - self.assertEqual(recv_expect, recv) - - def test_simple_send_direct_recv(self): - addr = pick_addr() - recv = background("direct_recv", "-a", addr) - while not "listening" in recv.stdout.readline(): - pass - self.assertEqual("all messages confirmed\n", execute("simple_send", "-a", addr)) - recv_expect = "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)]) - self.assertEqual(recv_expect, verify(recv)) - - def test_simple_recv_direct_send(self): - addr = pick_addr() - send = background("direct_send", "-a", addr) - while not "listening" in send.stdout.readline(): - pass - recv_expect = "simple_recv listening on amqp://%s\n" % (addr) - recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)]) - self.assertEqual(recv_expect, execute("simple_recv", "-a", addr)) - send_expect = "all messages confirmed\n" - self.assertEqual(send_expect, verify(send)) - - 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. -All mimsy were the borogroves, => ALL MIMSY WERE THE BOROGROVES, -And the mome raths outgrabe. => AND THE MOME RATHS OUTGRABE. -""" - def test_simple_recv_send(self): - # Start receiver first, then run sender""" - b = Broker.get() - recv = background("simple_recv", "-a", b.addr) - self.assertEqual("all messages confirmed\n", execute("simple_send", "-a", b.addr)) - recv_expect = "simple_recv listening on amqp://%s\n" % (b.addr) - recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)]) - self.assertEqual(recv_expect, verify(recv)) - - def test_client_server(self): - b = Broker.get() - server = background("server", "-a", b.addr) - try: - self.assertEqual(execute("client", "-a", b.addr), self.CLIENT_EXPECT) - finally: - server.kill() - -if __name__ == "__main__": - unittest.main() http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b4fa65a/examples/cpp/engine/helloworld.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/engine/helloworld.cpp b/examples/cpp/engine/helloworld.cpp index 4440e4d..43c4a03 100644 --- a/examples/cpp/engine/helloworld.cpp +++ b/examples/cpp/engine/helloworld.cpp @@ -54,7 +54,6 @@ class hello_world : public proton::handler { int main(int argc, char **argv) { try { proton::url url(argc > 1 ? argv[1] : "127.0.0.1:5672/examples"); - hello_world hw(url.path()); proton::io::socket_engine(url, hw).run(); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b4fa65a/examples/cpp/example_test.py ---------------------------------------------------------------------- diff --git a/examples/cpp/example_test.py b/examples/cpp/example_test.py index 9aa390c..d6675ff 100644 --- a/examples/cpp/example_test.py +++ b/examples/cpp/example_test.py @@ -20,179 +20,210 @@ # This is a test script to run the examples and verify that they behave as expected. import unittest -import os, sys, socket, time +import os, sys, socket, time, re from random import randrange from subprocess import Popen, PIPE, STDOUT from copy import copy import platform from os.path import dirname as dirname +from threading import Thread, Event -def cmdline(*args): - """Adjust executable name args[0] for windows and/or valgrind""" - args = list(args) - if platform.system() == "Windows": - args[0] += ".exe" - if "VALGRIND" in os.environ and os.environ["VALGRIND"]: - args = [os.environ["VALGRIND"], "--error-exitcode=42", "--quiet", - "--leak-check=full"] + args - return args - -def background(*args): - """Run executable in the backround, return the popen""" - p = Popen(cmdline(*args), stdout=PIPE, stderr=sys.stderr) - p.args = args # Save arguments for debugging output - return p - -def verify(p): - """Wait for executable to exit and verify status.""" - try: - out, err = p.communicate() - except Exception as e: - raise Exception("Error running %s: %s", p.args, e) - if p.returncode: - raise Exception("""%s exit code %s -vvvvvvvvvvvvvvvv -%s -^^^^^^^^^^^^^^^^ -""" % (p.args, p.returncode, out)) - if platform.system() == "Windows": - # Just \n please +def pick_addr(): + """Pick a new host:port address.""" + # TODO Conway 2015-07-14: need a safer way to pick ports. + p = randrange(10000, 20000) + return "127.0.0.1:%s" % p + +class ProcError(Exception): + """An exception that captures failed process output""" + def __init__(self, proc, what="non-0 exit"): + out = proc.out.strip() if out: - out = out.translate(None, '\r') - return out + out = "\nvvvvvvvvvvvvvvvv\n%s\n^^^^^^^^^^^^^^^^\n" % out + else: + out = ", no output)" + super(Exception, self, ).__init__( + "%s %s, code=%s%s" % (proc.args, what, proc.returncode, out)) -def execute(*args): - return verify(background(*args)) +class Proc(Popen): + """A example process that stores its stdout and can scan it for a 'ready' pattern'""" -NULL = open(os.devnull, 'w') + if "VALGRIND" in os.environ and os.environ["VALGRIND"]: + env_args = [os.environ["VALGRIND"], "--error-exitcode=42", "--quiet", "--leak-check=full"] + else: + env_args = [] -def wait_addr(addr, timeout=10): - """Wait up to timeout for something to listen on port""" - deadline = time.time() + timeout - while time.time() < deadline: + def __init__(self, args, ready=None, timeout=10, **kwargs): + """Start an example process""" + args = list(args) + if platform.system() == "Windows": + args[0] += ".exe" + self.timeout = timeout + self.args = args + self.out = "" + args = self.env_args + args try: - c = socket.create_connection(addr.split(":"), deadline - time.time()) - c.close() - return - except socket.error as e: - time.sleep(0.01) - raise Exception("Timed out waiting for %s", addr) + Popen.__init__(self, args, stdout=PIPE, stderr=STDOUT, **kwargs) + except Exception, e: + raise ProcError(self, str(e)) + # Start reader thread. + self.pattern = ready + self.ready = Event() + self.error = None + self.thread = Thread(target=self.run_) + self.thread.daemon = True + self.thread.start() + if self.pattern: + self.wait_ready() -def pick_addr(): - """Pick a new host:port address.""" - # TODO aconway 2015-07-14: need a safer way to pick ports. - p = randrange(10000, 20000) - return "127.0.0.1:%s" % p + def run_(self): + try: + while True: + l = self.stdout.readline() + if not l: break + self.out += l.translate(None, "\r") + if self.pattern is not None: + if re.search(self.pattern, l): + self.ready.set() + if self.wait() != 0: + self.error = ProcError(self) + except Exception, e: + self.error = sys.exc_info() + finally: + self.ready.set() + + def safe_kill(self): + """Kill and clean up zombie but don't wait forever. No exceptions.""" + try: + self.kill() + self.thread.join(self.timeout) + except: pass + return self.out + + def check_(self): + if self.error: + if isinstance(self.error, Exception): + raise self.error + raise self.error[0], self.error[1], self.error[2] # with traceback + + def wait_ready(self): + """Wait for ready to appear in output""" + if self.ready.wait(self.timeout): + self.check_() + return self.out + else: + self.safe_kill() + raise ProcError(self, "timeout waiting for '%s'" % self.pattern) + + def wait_exit(self): + """Wait for process to exit, return output. Raise ProcError on failure.""" + self.thread.join(self.timeout) + if self.poll() is not None: + self.check_() + return self.out + else: + raise ProcError(self, "timeout waiting for exit") -def ssl_certs_dir(): - """Absolute path to the test SSL certificates""" - pn_root = dirname(dirname(dirname(sys.argv[0]))) - return os.path.join(pn_root, "examples/cpp/ssl_certs") -class Broker(object): - """Run the test broker""" +class ExampleTestCase(unittest.TestCase): + def setUp(self): + self.procs = [] + + def tearDown(self): + for p in self.procs: + p.safe_kill() + + def proc(self, *args, **kwargs): + p = Proc(*args, **kwargs) + self.procs.append(p) + return p + + +class BrokerTestCase(ExampleTestCase): + """ + ExampleTest that starts a broker in setUpClass and kills it in tearDownClass. + """ @classmethod - def get(cls): - if not hasattr(cls, "_broker"): - cls._broker = Broker() - return cls._broker + def setUpClass(cls): + cls.addr = pick_addr() + "/examples" + cls.broker = Proc(["broker", "-a", cls.addr], ready="listening") + cls.broker.wait_ready() @classmethod - def stop(cls): - if cls.get() and cls._broker.process: - cls._broker.process.kill() - cls._broker = None - - def __init__(self): - broker_exe = os.environ.get("TEST_BROKER") or "broker" - self.addr = pick_addr() - cmd = cmdline(broker_exe, "-a", self.addr) - try: - self.process = Popen(cmd, stdout=NULL, stderr=sys.stderr) - wait_addr(self.addr) - self.addr += "/examples" - except Exception as e: - raise Exception("Error running %s: %s", cmd, e) + def tearDownClass(cls): + cls.broker.safe_kill() -class ExampleTest(unittest.TestCase): - """Run the examples, verify they behave as expected.""" + def tearDown(self): + super(BrokerTestCase, self).tearDown() + b = type(self).broker + if b.poll() != None: # Broker crashed + type(self).setUpClass() # Start another for the next test. + raise ProcError(b, "broker crash") - @classmethod - def tearDownClass(self): - Broker.stop() + +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. +All mimsy were the borogroves, => ALL MIMSY WERE THE BOROGROVES, +And the mome raths outgrabe. => AND THE MOME RATHS OUTGRABE. +""" + +def recv_expect(name, addr): + return "%s listening on amqp://%s\n%s" % ( + name, addr, "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)])) + +class ContainerExampleTest(BrokerTestCase): + """Run the container examples, verify they behave as expected.""" def test_helloworld(self): - b = Broker.get() - hw = execute("helloworld", b.addr) - self.assertEqual('Hello World!\n', hw) + self.assertEqual('Hello World!\n', self.proc(["helloworld", self.addr]).wait_exit()) def test_helloworld_direct(self): - addr = pick_addr() - hw = execute("helloworld_direct", addr) - self.assertEqual('Hello World!\n', hw) + self.assertEqual('Hello World!\n', self.proc(["helloworld_direct", pick_addr()]).wait_exit()) def test_simple_send_recv(self): - b = Broker.get() - send = execute("simple_send", "-a", b.addr) - self.assertEqual("all messages confirmed\n", send) - recv = execute("simple_recv", "-a", b.addr) - recv_expect = "simple_recv listening on amqp://%s\n" % (b.addr) - recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)]) - self.assertEqual(recv_expect, recv) + self.assertEqual("all messages confirmed\n", + self.proc(["simple_send", "-a", self.addr]).wait_exit()) + self.assertEqual(recv_expect("simple_recv", self.addr), self.proc(["simple_recv", "-a", self.addr]).wait_exit()) + + def test_simple_recv_send(self): + # Start receiver first, then run sender""" + recv = self.proc(["simple_recv", "-a", self.addr]) + self.assertEqual("all messages confirmed\n", + self.proc(["simple_send", "-a", self.addr]).wait_exit()) + self.assertEqual(recv_expect("simple_recv", self.addr), recv.wait_exit()) + def test_simple_send_direct_recv(self): addr = pick_addr() - recv = background("direct_recv", "-a", addr) - wait_addr(addr) - self.assertEqual("all messages confirmed\n", execute("simple_send", "-a", addr)) - recv_expect = "direct_recv listening on amqp://%s\n" % (addr) - recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)]) - self.assertEqual(recv_expect, verify(recv)) + recv = self.proc(["direct_recv", "-a", addr], "listening") + self.assertEqual("all messages confirmed\n", + self.proc(["simple_send", "-a", addr]).wait_exit()) + self.assertEqual(recv_expect("direct_recv", addr), recv.wait_exit()) def test_simple_recv_direct_send(self): addr = pick_addr() - send = background("direct_send", "-a", addr) - wait_addr(addr) - recv_expect = "simple_recv listening on amqp://%s\n" % (addr) - recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)]) - self.assertEqual(recv_expect, execute("simple_recv", "-a", addr)) - send_expect = "direct_send listening on amqp://%s\nall messages confirmed\n" % (addr) - self.assertEqual(send_expect, verify(send)) - - 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. -All mimsy were the borogroves, => ALL MIMSY WERE THE BOROGROVES, -And the mome raths outgrabe. => AND THE MOME RATHS OUTGRABE. -""" - def test_simple_recv_send(self): - # Start receiver first, then run sender""" - b = Broker.get() - recv = background("simple_recv", "-a", b.addr) - self.assertEqual("all messages confirmed\n", execute("simple_send", "-a", b.addr)) - recv_expect = "simple_recv listening on amqp://%s\n" % (b.addr) - recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)]) - self.assertEqual(recv_expect, verify(recv)) + send = self.proc(["direct_send", "-a", addr], "listening") + self.assertEqual(recv_expect("simple_recv", addr), + self.proc(["simple_recv", "-a", addr]).wait_exit()) + + self.assertEqual( + "direct_send listening on amqp://%s\nall messages confirmed\n" % addr, + send.wait_exit()) def test_request_response(self): - b = Broker.get() - server = background("server", "-a", b.addr) - try: - self.assertEqual(execute("client", "-a", b.addr), self.CLIENT_EXPECT) - finally: - server.kill() + server = self.proc(["server", "-a", self.addr], "connected") + self.assertEqual(CLIENT_EXPECT, + self.proc(["client", "-a", self.addr]).wait_exit()) def test_request_response_direct(self): addr = pick_addr() - server = background("server_direct", "-a", addr+"/examples") - wait_addr(addr) - try: - self.assertEqual(execute("client", "-a", addr+"/examples"), self.CLIENT_EXPECT) - finally: - server.kill() + server = self.proc(["server_direct", "-a", addr+"/examples"], "listening") + self.assertEqual(CLIENT_EXPECT, + self.proc(["client", "-a", addr+"/examples"]).wait_exit()) def test_encode_decode(self): - expect=""" + want=""" == Array, list and map of uniform type. array<int>[int(1), int(2), int(3)] [ 1 2 3 ] @@ -215,7 +246,7 @@ list[int(42), boolean(false), symbol(x)] map{string(k1):int(42), symbol(k2):boolean(false)} """ self.maxDiff = None - self.assertEqual(expect, execute("encode_decode")) + self.assertEqual(want, self.proc(["encode_decode"]).wait_exit()) def test_recurring_timer(self): env = copy(os.environ) # Disable valgrind, this test is time-sensitive. @@ -227,18 +258,22 @@ Tick... Tock... """ self.maxDiff = None - self.assertEqual(expect, execute("recurring_timer", "-t", ".05", "-k", ".01")) + self.assertEqual(expect, self.proc(["recurring_timer", "-t", ".05", "-k", ".01"]).wait_exit()) finally: os.environ = env # Restore environment + def ssl_certs_dir(self): + """Absolute path to the test SSL certificates""" + pn_root = dirname(dirname(dirname(sys.argv[0]))) + return os.path.join(pn_root, "examples/cpp/ssl_certs") + def test_ssl(self): # SSL without SASL - expect="""Outgoing client connection connected via SSL. Server certificate identity CN=test_server -Hello World! -""" addr = "amqps://" + pick_addr() + "/examples" - ignore_first_line, ignore_nl, ssl_hw = execute("ssl", addr, ssl_certs_dir()).partition('\n') - self.assertEqual(expect, ssl_hw) + out = self.proc(["ssl", addr, self.ssl_certs_dir()]).wait_exit() + expect = "Outgoing client connection connected via SSL. Server certificate identity CN=test_server\nHello World!" + self.assertIn(expect, out) + def test_ssl_client_cert(self): # SSL with SASL EXTERNAL @@ -247,8 +282,48 @@ Outgoing client connection connected via SSL. Server certificate identity CN=te Hello World! """ addr = "amqps://" + pick_addr() + "/examples" - ignore_first_line, ignore_nl, ssl_hw = execute("ssl_client_cert", addr, ssl_certs_dir()).partition('\n') - self.assertEqual(expect, ssl_hw) + out = self.proc(["ssl_client_cert", addr, self.ssl_certs_dir()]).wait_exit() + self.assertIn(expect, out) + + +class ConnectionEngineExampleTest(BrokerTestCase): + """Run the connction_engine examples, verify they behave as expected.""" + + def test_helloworld(self): + self.assertEqual('Hello World!\n', + self.proc(["helloworld", self.addr]).wait_exit()) + + def test_simple_send_recv(self): + self.assertEqual("all messages confirmed\n", + self.proc(["simple_send", "-a", self.addr]).wait_exit()) + self.assertEqual(recv_expect("simple_recv", self.addr), self.proc(["simple_recv", "-a", self.addr]).wait_exit()) + + def test_simple_recv_send(self): + # Start receiver first, then run sender""" + recv = self.proc(["simple_recv", "-a", self.addr]) + self.assertEqual("all messages confirmed\n", self.proc(["simple_send", "-a", self.addr]).wait_exit()) + self.assertEqual(recv_expect("simple_recv", self.addr), recv.wait_exit()) + + + def test_simple_send_direct_recv(self): + addr = pick_addr() + recv = self.proc(["direct_recv", "-a", addr], "listening") + self.assertEqual("all messages confirmed\n", + self.proc(["simple_send", "-a", addr]).wait_exit()) + self.assertEqual(recv_expect("direct_recv", addr), recv.wait_exit()) + + def test_simple_recv_direct_send(self): + addr = pick_addr() + send = self.proc(["direct_send", "-a", addr], "listening") + self.assertEqual(recv_expect("simple_recv", addr), + self.proc(["simple_recv", "-a", addr]).wait_exit()) + self.assertEqual("direct_send listening on amqp://%s\nall messages confirmed\n" % addr, + send.wait_exit()) + + def test_request_response(self): + server = self.proc(["server", "-a", self.addr], "connected") + self.assertEqual(CLIENT_EXPECT, + self.proc(["client", "-a", self.addr]).wait_exit()) if __name__ == "__main__": unittest.main() http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b4fa65a/examples/cpp/helloworld.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/helloworld.cpp b/examples/cpp/helloworld.cpp index a969f27..5d92981 100644 --- a/examples/cpp/helloworld.cpp +++ b/examples/cpp/helloworld.cpp @@ -57,7 +57,6 @@ int main(int argc, char **argv) { hello_world hw(url); proton::container(hw).run(); - return 0; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b4fa65a/examples/cpp/server.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/server.cpp b/examples/cpp/server.cpp index d913ee1..8ac34cc 100644 --- a/examples/cpp/server.cpp +++ b/examples/cpp/server.cpp @@ -71,7 +71,7 @@ class server : public proton::handler { if (!senders[reply_to]) { senders[reply_to] = connection.open_sender(reply_to); } - + senders[reply_to].send(reply); } }; @@ -84,7 +84,7 @@ int main(int argc, char **argv) { try { opts.parse(); - + server srv(address); proton::container(srv).run(); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
