PROTON-1798: [c, cpp, ruby] Installable tests for proton

Tests can be executed from install for c, cpp, ruby.
See tests/share/examples-README.md

RUNTIME_CHECK=memcheck, helgrind are supported for normal builds.
asan, tsan require a special library build so less likely to be useful for 
install tests.

TODO:
- python, go examples
- non-example tests installed under share/pronton-VERSION/tests/<language>


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

Branch: refs/heads/go1
Commit: 393f8a67712d126f98b3a87e83fdafab57011239
Parents: 6c765bc
Author: Alan Conway <acon...@redhat.com>
Authored: Mon Sep 10 17:13:09 2018 -0400
Committer: Alan Conway <acon...@redhat.com>
Committed: Tue Sep 11 12:07:56 2018 -0400

----------------------------------------------------------------------
 CMakeLists.txt                 |   7 +-
 c/CMakeLists.txt               |   1 +
 c/examples/CMakeLists.txt      |  33 +++---
 c/examples/example_test.py     | 115 -------------------
 c/examples/testme              | 111 ++++++++++++++++++
 cpp/CMakeLists.txt             |   1 +
 cpp/examples/CMakeLists.txt    |  40 ++++---
 cpp/examples/example_test.py   | 216 ------------------------------------
 cpp/examples/testme            | 213 +++++++++++++++++++++++++++++++++++
 go/CMakeLists.txt              |   5 +-
 python/CMakeLists.txt          |   5 +-
 ruby/CMakeLists.txt            |  20 ++--
 ruby/examples/example_test.rb  | 110 ------------------
 ruby/examples/testme           | 110 ++++++++++++++++++
 runtime_check.cmake            | 123 --------------------
 tests/py/test_subprocess.py    |  10 +-
 tests/runtime_check.cmake      | 123 ++++++++++++++++++++
 tests/share/CMakeLists.txt     |  42 +++++++
 tests/share/README.txt         |   3 +
 tests/share/examples-README.md |  20 ++++
 20 files changed, 692 insertions(+), 616 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 105f22e..b9e1656 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,7 +39,7 @@ find_package (CyrusSASL)
 enable_testing ()
 
 # Set up runtime checks (valgrind, sanitizers etc.)
-include(runtime_check.cmake)  
+include(tests/runtime_check.cmake)  
 
 ## Variables used across components
 
@@ -394,8 +394,9 @@ endforeach(BINDING)
 
 unset(BUILD_BINDINGS CACHE) # Remove from cache, only relevant when creating 
the initial cache.
 
-install (FILES LICENSE.txt README.md
-         DESTINATION ${PROTON_SHARE})
+install (FILES LICENSE.txt README.md tests/share/CMakeLists.txt DESTINATION 
${PROTON_SHARE})
+install (FILES tests/share/examples-README.md RENAME README.md DESTINATION 
${PROTON_SHARE}/examples)
+install (DIRECTORY tests DESTINATION ${PROTON_SHARE} PATTERN share EXCLUDE)
 
 # Generate test environment settings
 configure_file(${CMAKE_SOURCE_DIR}/misc/config.sh.in

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt
index a16f46b..effb96b 100644
--- a/c/CMakeLists.txt
+++ b/c/CMakeLists.txt
@@ -601,4 +601,5 @@ add_subdirectory(tools)
 
 install (DIRECTORY examples/
          DESTINATION "${PROTON_SHARE}/examples/c"
+         USE_SOURCE_PERMISSIONS
          PATTERN ProtonConfig.cmake EXCLUDE)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/c/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/c/examples/CMakeLists.txt b/c/examples/CMakeLists.txt
index b04e444..8526ffe 100644
--- a/c/examples/CMakeLists.txt
+++ b/c/examples/CMakeLists.txt
@@ -34,20 +34,23 @@ foreach (name broker send receive direct send-abort 
send-ssl)
 endforeach()
 
 
-# Add a test to run all examples
+find_package (PythonInterp)     # For test-driver script
+if (PYTHON_EXECUTABLE)
+  if(WIN32)
+    # NOTE: need to escape semicolons as cmake uses them as list separators.
+    set(test_path 
"$<TARGET_FILE_DIR:c-broker>\;$<TARGET_FILE_DIR:qpid-proton-core>\;$<TARGET_FILE_DIR:qpid-proton-proactor>")
+  else()
+    set(test_path "$<TARGET_FILE_DIR:c-broker>:$ENV{PATH}")
+  endif()
 
-# Make correct environment to find test executables and valgrind.
-if(WIN32)
-  set(test_path 
"$<TARGET_FILE_DIR:c-broker>;$<TARGET_FILE_DIR:qpid-proton-core>;$<TARGET_FILE_DIR:qpid-proton-proactor>")
-else()
-  set(test_path "$<TARGET_FILE_DIR:c-broker>:$ENV{PATH}")
-endif()
+  set(test_env
+    "PATH=${test_path}"
+    "PYTHONPATH=../../tests/py"
+    ${TEST_ENV})
 
-add_test(
-  NAME c-example-tests
-  COMMAND ${PN_ENV_SCRIPT}
-  "PATH=${test_path}"
-  "PYTHONPATH=${CMAKE_SOURCE_DIR}/tests/py"
-  ${TEST_ENV} --
-  ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v
-  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+  add_test(
+    NAME c-example-tests
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+    COMMAND ${PYTHON_EXECUTABLE} testme -v)
+  set_tests_properties(c-example-tests PROPERTIES ENVIRONMENT "${test_env}")
+endif()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/c/examples/example_test.py
----------------------------------------------------------------------
diff --git a/c/examples/example_test.py b/c/examples/example_test.py
deleted file mode 100644
index 35a8993..0000000
--- a/c/examples/example_test.py
+++ /dev/null
@@ -1,115 +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
-#
-
-# Run the C examples and verify that they behave as expected.
-# Example executables must be in PATH
-
-import unittest
-
-from test_subprocess import Popen, TestProcessError, check_output
-
-class Server(Popen):
-    def __init__(self, *args, **kwargs):
-        super(Server, self).__init__(*args, **kwargs)
-        self.port = self.expect("listening on ([0-9]+)$").group(1)
-
-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
-
-class Broker(Server):
-    def __init__(self):
-        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, "", port, "xtest", str(messages)])
-
-    def startex(self, name, port, messages=MESSAGES):
-        """Start an example sub-process with standard arguments"""
-        return Popen([name, "", port, "xtest", str(messages)])
-
-    def test_send_receive(self):
-        """Send first then receive"""
-        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() as b:
-            r = self.startex("receive", b.port)
-            self.assertEqual(send_expect(), self.runex("send", b.port))
-            self.assertMultiLineEqual(receive_expect(), r.communicate()[0])
-
-    def test_send_direct(self):
-        """Send to direct server"""
-        d = Server(["direct", "", "0"])
-        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 =  Server(["direct", "", "0"])
-        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 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)
-            self.assertMultiLineEqual(expect, self.runex("receive", b.port, 
"20"))
-
-    def test_send_abort_direct(self):
-        """Send aborted messages to the direct server"""
-        d = Server(["direct", "", "0", "examples", "20"])
-        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"""
-        try:
-            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 TestProcessError as e:
-            if e.output and e.output.startswith(b"error initializing SSL"):
-                print("Skipping %s: SSL not available" % self.id())
-            else:
-                raise
-
-if __name__ == "__main__":
-    unittest.main()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/c/examples/testme
----------------------------------------------------------------------
diff --git a/c/examples/testme b/c/examples/testme
new file mode 100755
index 0000000..c498293
--- /dev/null
+++ b/c/examples/testme
@@ -0,0 +1,111 @@
+#!/usr/bin/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
+#
+
+# Run the C examples and verify that they behave as expected.
+# Example executables must be in PATH
+
+import unittest
+
+from test_subprocess import Popen, Server, TestProcessError, check_output
+
+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
+
+class Broker(Server):
+    def __init__(self):
+        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, "", port, "xtest", str(messages)])
+
+    def startex(self, name, port, messages=MESSAGES):
+        """Start an example sub-process with standard arguments"""
+        return Popen([name, "", port, "xtest", str(messages)])
+
+    def test_send_receive(self):
+        """Send first then receive"""
+        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() as b:
+            r = self.startex("receive", b.port)
+            self.assertEqual(send_expect(), self.runex("send", b.port))
+            self.assertMultiLineEqual(receive_expect(), r.communicate()[0])
+
+    def test_send_direct(self):
+        """Send to direct server"""
+        d = Server(["direct", "", "0"])
+        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 =  Server(["direct", "", "0"])
+        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 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)
+            self.assertMultiLineEqual(expect, self.runex("receive", b.port, 
"20"))
+
+    def test_send_abort_direct(self):
+        """Send aborted messages to the direct server"""
+        d = Server(["direct", "", "0", "examples", "20"])
+        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"""
+        try:
+            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 TestProcessError as e:
+            if e.output and e.output.startswith(b"error initializing SSL"):
+                print("Skipping %s: SSL not available" % self.id())
+            else:
+                raise
+
+if __name__ == "__main__":
+    unittest.main()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index a06e67d..d0b3cfb 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -198,6 +198,7 @@ install (DIRECTORY "include/proton" DESTINATION 
${INCLUDE_INSTALL_DIR} FILES_MAT
 install (FILES "${CMAKE_CURRENT_BINARY_DIR}/config_presets.hpp" DESTINATION 
"${INCLUDE_INSTALL_DIR}/proton/internal")
 install (DIRECTORY "examples/"
   DESTINATION "${PROTON_SHARE}/examples/cpp"
+  USE_SOURCE_PERMISSIONS
   PATTERN "ProtonCppConfig.cmake" EXCLUDE)
 
 add_subdirectory(examples)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/cpp/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/cpp/examples/CMakeLists.txt b/cpp/examples/CMakeLists.txt
index ba18d83..35ad01c 100644
--- a/cpp/examples/CMakeLists.txt
+++ b/cpp/examples/CMakeLists.txt
@@ -23,7 +23,7 @@ enable_language(CXX)
 set (ProtonCpp_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 find_package(ProtonCpp REQUIRED)
 set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
-find_package(Threads)
+find_package(Threads REQUIRED)
 
 include_directories(${ProtonCpp_INCLUDE_DIRS})
 link_libraries(${ProtonCpp_LIBRARIES})
@@ -103,26 +103,32 @@ if(HAS_ENOUGH_CPP11)
   endif()
 endif()
 
-# Add a test with the correct environment to find test executables and 
valgrind.
-macro(add_cpp_example_test name)
+find_package (PythonInterp)     # For test-driver script
+if (PYTHON_EXECUTABLE)
   if(WIN32)
-    set(test_path 
"$<TARGET_FILE_DIR:broker>;$<TARGET_FILE_DIR:qpid-proton>;$<TARGET_FILE_DIR:qpid-proton-cpp>")
-  else(WIN32)
+    # NOTE: need to escape semicolons as cmake uses them as list separators.
+    set(test_path 
"$<TARGET_FILE_DIR:broker>\;$<TARGET_FILE_DIR:qpid-proton-core>\;$<TARGET_FILE_DIR:qpid-proton-cpp>")
+  else()
     set(test_path "$<TARGET_FILE_DIR:broker>:$ENV{PATH}")
-  endif(WIN32)
-  add_test(
-    NAME ${name}
-    COMMAND ${PN_ENV_SCRIPT}
+  endif()
+
+  set(test_env
     "PATH=${test_path}"
-    "PYTHONPATH=${CMAKE_SOURCE_DIR}/tests/py"
+    "PYTHONPATH=../../tests/py"
     "HAS_CPP11=$<$<BOOL:${HAS_ENOUGH_CPP11}>:1>"
-    ${TEST_ENV} --
-    ${ARGN}
-    )
-endmacro()
+    ${TEST_ENV})
 
-add_cpp_example_test(cpp-example-container ${PYTHON_EXECUTABLE} 
${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleTest)
+  add_test(
+    NAME cpp-example-container
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+    COMMAND ${PYTHON_EXECUTABLE} testme -v ContainerExampleTest)
+  set_tests_properties(cpp-example-container PROPERTIES ENVIRONMENT 
"${test_env}")
 
-if (NOT SSL_IMPL STREQUAL none)
-add_cpp_example_test(cpp-example-container-ssl ${PYTHON_EXECUTABLE} 
${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleSSLTest)
+  if (NOT SSL_IMPL STREQUAL none)
+    add_test(
+      NAME cpp-example-container-ssl
+      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+      COMMAND ${PYTHON_EXECUTABLE}  testme -v ContainerExampleSSLTest)
+    set_tests_properties(cpp-example-container-ssl PROPERTIES ENVIRONMENT 
"${test_env}")
+  endif()
 endif()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/cpp/examples/example_test.py
----------------------------------------------------------------------
diff --git a/cpp/examples/example_test.py b/cpp/examples/example_test.py
deleted file mode 100644
index 38a9a6e..0000000
--- a/cpp/examples/example_test.py
+++ /dev/null
@@ -1,216 +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
-#
-
-# Run the C++ examples and verify that they behave as expected.
-# Example executables must be in PATH
-
-import unittest, sys, shutil, os
-from test_subprocess import Popen, TestProcessError, check_output
-from os.path import dirname
-from string import Template
-
-class Server(Popen):
-    """A process that prints 'listening on <port>' to stdout"""
-    def __init__(self, *args, **kwargs):
-        super(Server, self).__init__(*args, **kwargs)
-        self.port = self.expect("listening on ([0-9]+)$").group(1)
-
-    @property
-    def addr(self):
-        return ":%s/example" % self.port
-
-def _cyrusSetup(conf_dir):
-  """Write out simple SASL config.tests
-  """
-  saslpasswd = os.getenv('SASLPASSWD')
-  if 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)
-    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')
-    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)
-    check_output(args=cmd, shell=True)
-    os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir
-
-# Globally initialize Cyrus SASL configuration
-_cyrusSetup('sasl-conf')
-
-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.
-All mimsy were the borogroves, => ALL MIMSY WERE THE BOROGROVES,
-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(unittest.TestCase):
-    """Run the container examples, verify they behave as expected."""
-
-    def test_helloworld(self):
-      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])
-        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 = 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 = 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):
-        with Popen(["server", Broker.addr, "example"], kill_me=True) as server:
-            server.expect("connected to %s" % Broker.addr)
-            self.assertMultiLineEqual(CLIENT_EXPECT, check_output(["client", 
"-a", Broker.addr]))
-
-    def test_request_response_direct(self):
-        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
-success: Example 2: basic drain
-success: Example 3: drain without credit
-success: Example 4: high/low watermark
-"""
-        self.assertMultiLineEqual(want, check_output(["flow_control", 
"--quiet"]))
-
-    def test_encode_decode(self):
-        want="""
-== Array, list and map of uniform type.
-array<int>[int(1), int(2), int(3)]
-[ 1 2 3 ]
-list[int(1), int(2), int(3)]
-[ 1 2 3 ]
-map{string(one):int(1), string(two):int(2)}
-{ one:1 two:2 }
-map{string(z):int(3), string(a):int(4)}
-[ z:3 a:4 ]
-list[string(a), string(b), string(c)]
-
-== List and map of mixed type values.
-list[int(42), string(foo)]
-[ 42 foo ]
-map{int(4):string(four), string(five):int(5)}
-{ 4:four five:5 }
-
-== Insert with stream operators.
-array<int>[int(1), int(2), int(3)]
-list[int(42), boolean(0), symbol(x)]
-map{string(k1):int(42), symbol(k2):boolean(0)}
-"""
-        self.maxDiff = None
-        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 = 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 = 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)
-
-    def test_message_properties(self):
-        expect="""using put/get: short=123 string=foo symbol=sym
-using coerce: short(as long)=123
-props[short]=123
-props[string]=foo
-props[symbol]=sym
-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, check_output(["message_properties"]))
-
-    @unittest.skipUnless(os.getenv('HAS_CPP11'), "not a  C++11 build")
-    def test_multithreaded_client(self):
-        got = check_output(["multithreaded_client", Broker.addr, "examples", 
"10"])
-        self.maxDiff = None
-        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 = check_output(["multithreaded_client_flow_control", Broker.addr, 
"examples", "10", "2"])
-        self.maxDiff = None
-        self.assertIn("20 messages sent and received", got);
-
-class ContainerExampleSSLTest(unittest.TestCase):
-    """Run the SSL container examples, verify they behave as expected."""
-
-    def ssl_certs_dir(self):
-        """Absolute path to the test SSL certificates"""
-        return os.path.join(dirname(sys.argv[0]), "ssl-certs")
-
-    def test_ssl(self):
-        # SSL without SASL, VERIFY_PEER_NAME
-        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):
-        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 = check_output(["ssl", "-c", self.ssl_certs_dir(), "-v", "fail"])
-        expect = "Expected failure of connection with wrong peer name"
-        self.assertIn(expect, out)
-
-    def test_ssl_client_cert(self):
-        # SSL with SASL EXTERNAL
-        expect="""Inbound client certificate identity CN=test_client
-Outgoing client connection connected via SSL.  Server certificate identity 
CN=test_server
-Hello World!
-"""
-        out = check_output(["ssl_client_cert", self.ssl_certs_dir()])
-        self.assertIn(expect, out)
-
-if __name__ == "__main__":
-    with Broker() as b:
-      Broker.addr = b.addr
-      unittest.main()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/cpp/examples/testme
----------------------------------------------------------------------
diff --git a/cpp/examples/testme b/cpp/examples/testme
new file mode 100755
index 0000000..d4abc0a
--- /dev/null
+++ b/cpp/examples/testme
@@ -0,0 +1,213 @@
+#!/usr/bin/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
+#
+
+# Run the C++ examples and verify that they behave as expected.
+# Example executables must be in PATH
+
+import unittest, sys, shutil, os
+from test_subprocess import Popen, TestProcessError, check_output
+import test_subprocess
+from os.path import dirname
+from string import Template
+
+class Server(test_subprocess.Server):
+    @property
+    def addr(self):
+        return ":%s/example" % self.port
+
+def _cyrusSetup(conf_dir):
+  """Write out simple SASL config.tests
+  """
+  saslpasswd = os.getenv('SASLPASSWD')
+  if 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)
+    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')
+    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)
+    check_output(args=cmd, shell=True)
+    os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir
+
+# Globally initialize Cyrus SASL configuration
+_cyrusSetup('sasl-conf')
+
+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.
+All mimsy were the borogroves, => ALL MIMSY WERE THE BOROGROVES,
+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(unittest.TestCase):
+    """Run the container examples, verify they behave as expected."""
+
+    def test_helloworld(self):
+      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])
+        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 = 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 = 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):
+        with Popen(["server", Broker.addr, "example"], kill_me=True) as server:
+            server.expect("connected to %s" % Broker.addr)
+            self.assertMultiLineEqual(CLIENT_EXPECT, check_output(["client", 
"-a", Broker.addr]))
+
+    def test_request_response_direct(self):
+        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
+success: Example 2: basic drain
+success: Example 3: drain without credit
+success: Example 4: high/low watermark
+"""
+        self.assertMultiLineEqual(want, check_output(["flow_control", 
"--quiet"]))
+
+    def test_encode_decode(self):
+        want="""
+== Array, list and map of uniform type.
+array<int>[int(1), int(2), int(3)]
+[ 1 2 3 ]
+list[int(1), int(2), int(3)]
+[ 1 2 3 ]
+map{string(one):int(1), string(two):int(2)}
+{ one:1 two:2 }
+map{string(z):int(3), string(a):int(4)}
+[ z:3 a:4 ]
+list[string(a), string(b), string(c)]
+
+== List and map of mixed type values.
+list[int(42), string(foo)]
+[ 42 foo ]
+map{int(4):string(four), string(five):int(5)}
+{ 4:four five:5 }
+
+== Insert with stream operators.
+array<int>[int(1), int(2), int(3)]
+list[int(42), boolean(0), symbol(x)]
+map{string(k1):int(42), symbol(k2):boolean(0)}
+"""
+        self.maxDiff = None
+        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 = 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 = 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)
+
+    def test_message_properties(self):
+        expect="""using put/get: short=123 string=foo symbol=sym
+using coerce: short(as long)=123
+props[short]=123
+props[string]=foo
+props[symbol]=sym
+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, check_output(["message_properties"]))
+
+    @unittest.skipUnless(os.getenv('HAS_CPP11'), "not a  C++11 build")
+    def test_multithreaded_client(self):
+        got = check_output(["multithreaded_client", Broker.addr, "examples", 
"10"])
+        self.maxDiff = None
+        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 = check_output(["multithreaded_client_flow_control", Broker.addr, 
"examples", "10", "2"])
+        self.maxDiff = None
+        self.assertIn("20 messages sent and received", got);
+
+class ContainerExampleSSLTest(unittest.TestCase):
+    """Run the SSL container examples, verify they behave as expected."""
+
+    def ssl_certs_dir(self):
+        """Absolute path to the test SSL certificates"""
+        return os.path.join(dirname(sys.argv[0]), "ssl-certs")
+
+    def test_ssl(self):
+        # SSL without SASL, VERIFY_PEER_NAME
+        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):
+        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 = check_output(["ssl", "-c", self.ssl_certs_dir(), "-v", "fail"])
+        expect = "Expected failure of connection with wrong peer name"
+        self.assertIn(expect, out)
+
+    def test_ssl_client_cert(self):
+        # SSL with SASL EXTERNAL
+        expect="""Inbound client certificate identity CN=test_client
+Outgoing client connection connected via SSL.  Server certificate identity 
CN=test_server
+Hello World!
+"""
+        out = check_output(["ssl_client_cert", self.ssl_certs_dir()])
+        self.assertIn(expect, out)
+
+if __name__ == "__main__":
+    with Broker() as b:
+      Broker.addr = b.addr
+      unittest.main()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/go/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/go/CMakeLists.txt b/go/CMakeLists.txt
index 951f8a3..5887635 100644
--- a/go/CMakeLists.txt
+++ b/go/CMakeLists.txt
@@ -84,4 +84,7 @@ set (GO_INSTALL_DIR ${SHARE_INSTALL_DIR}/gocode/src CACHE 
PATH "Installation dir
 mark_as_advanced (GO_INSTALL_DIR)
 
 install(DIRECTORY src/qpid.apache.org DESTINATION ${GO_INSTALL_DIR} COMPONENT 
Go)
-install(DIRECTORY examples/ DESTINATION "${PROTON_SHARE}/examples/go" 
COMPONENT Go)
+install(DIRECTORY examples/
+  DESTINATION "${PROTON_SHARE}/examples/go"
+  COMPONENT Go
+  PATTERN "CMakeLists.txt" EXCLUDE)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/python/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 181128c..c9e659e 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -151,10 +151,7 @@ install(TARGETS ${SWIG_MODULE_cproton_REAL_NAME}
 install(DIRECTORY examples/
         DESTINATION "${PROTON_SHARE}/examples/python"
         COMPONENT Python
-        PATTERN "*.py"
-        PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
-                    GROUP_EXECUTE GROUP_READ
-                    WORLD_EXECUTE WORLD_READ)
+        USE_SOURCE_PERMISSIONS)
 
 set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES 
"html;tutorial")
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/ruby/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/ruby/CMakeLists.txt b/ruby/CMakeLists.txt
index eb99907..ca342dc 100644
--- a/ruby/CMakeLists.txt
+++ b/ruby/CMakeLists.txt
@@ -112,11 +112,7 @@ install(DIRECTORY lib/ DESTINATION ${RUBY_ARCHLIB_DIR} 
COMPONENT Ruby)
 install(DIRECTORY examples/
         DESTINATION "${PROTON_SHARE}/examples/ruby"
         COMPONENT Ruby
-        PATTERN "*.rb"
-        PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
-                    GROUP_EXECUTE GROUP_READ
-                    WORLD_EXECUTE WORLD_READ)
-
+        USE_SOURCE_PERMISSIONS)
 ## Tests
 
 
to_native_path("${src}/lib;${src}/tests;${src}/spec;${bin};${c_lib_dir};$ENV{RUBYLIB}"
 RUBYLIB)
@@ -138,10 +134,18 @@ if (result EQUAL 0)  # Have minitest
       NAME ${name}
       COMMAND ${test_env} ${TEST_WRAP_PREFIX_CMD} ${RUBY_EXECUTABLE} ${script} 
-v
       ${ARGN})
-
   endmacro()
-  add_ruby_test(example_test.rb WORKING_DIRECTORY 
${CMAKE_CURRENT_SOURCE_DIR}/examples)
-  add_ruby_test(old_example_test.rb WORKING_DIRECTORY 
${CMAKE_CURRENT_SOURCE_DIR}/tests/old-examples)
+
+  add_test(
+    NAME ruby-example-test
+    COMMAND ${test_env} ${RUBY_EXECUTABLE} testme -v
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples)
+
+  add_test(
+    NAME ruby-old-example-test
+    COMMAND ${test_env} ${RUBY_EXECUTABLE} old_example_test.rb -v
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/old-examples)
+
   file(GLOB TESTS tests/test_*.rb)
   file(GLOB SPECS spec/*_spec.rb)
   foreach(t ${TESTS} ${SPECS})

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/ruby/examples/example_test.rb
----------------------------------------------------------------------
diff --git a/ruby/examples/example_test.rb b/ruby/examples/example_test.rb
deleted file mode 100755
index 576acf2..0000000
--- a/ruby/examples/example_test.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-#!/usr/bin/env ruby
-#
-# 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.
-#
-
-require 'minitest/autorun'
-require 'qpid_proton'
-require 'socket'
-require 'rbconfig'
-
-begin
-  MiniTest::Test
-rescue NameError                # For older versions of MiniTest
-  MiniTest::Test = MiniTest::Unit::TestCase
-end
-
-def listening_port(s)
-  /Listening on ([0-9]+)/.match(s)[1]
-end
-
-def listening_url(s)
-  ":#{listening_port s}"
-end
-
-class ExampleTest < MiniTest::Test
-
-  def run_script(*args)
-    return IO.popen([ RbConfig.ruby ] + args.map { |a| a.to_s })
-  end
-
-  def assert_output(want, *args)
-    assert_equal(want.strip, run_script(*args).read.strip)
-  end
-
-  def test_helloworld
-    assert_output("Hello world!", "helloworld.rb", $url, "examples")
-  end
-
-  def test_client_server
-    want =  <<EOS
--> 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.
-EOS
-    server = run_script("server.rb", $url, "examples")
-    assert_output(want.strip, "client.rb", $url, "examples")
-  ensure
-    Process.kill :TERM, server.pid if server
-  end
-
-  def test_send_recv
-    assert_output("All 10 messages confirmed!", "simple_send.rb", $url, 
"examples")
-    want = (0..9).reduce("") { |x,y| x << "Received: sequence #{y}\n" }
-    assert_output(want.strip, "simple_recv.rb", $url, "examples")
-  end
-
-  def test_ssl_send_recv
-    skip 'SSL not available' unless Qpid::Proton::SSL.present?
-    out = run_script("ssl_send.rb", $url, "examples").read.strip
-    assert_match(/Connection secured with "...*\"\nAll 10 messages 
confirmed!/, out)
-    want = (0..9).reduce("") { |x,y| x << "Received: sequence #{y}\n" }
-    assert_output(want.strip, "simple_recv.rb", $url, "examples")
-  end
-
-  def test_direct_recv
-    p = run_script("direct_recv.rb", ":0", "examples")
-    url = listening_url(p.readline) # Wait till ready
-    assert_output("All 10 messages confirmed!", "simple_send.rb", url, 
"examples")
-    want = (0..9).reduce("") { |x,y| x << "Received: sequence #{y}\n" }
-    assert_equal(want.strip, p.read.strip)
-  end
-
-  def test_direct_send
-    p = run_script("direct_send.rb", ":0", "examples")
-    url = listening_url(p.readline) # Wait till ready
-    want = (0..9).reduce("") { |x,y| x << "Received: sequence #{y}\n" }
-    assert_output(want.strip, "simple_recv.rb", url, "examples")
-    assert_equal("All 10 messages confirmed!", p.read.strip)
-  end
-end
-
-# Start the broker before all tests.
-$broker = IO.popen([RbConfig.ruby, 'broker.rb', ":0"])
-l = $broker.readline
-$url = listening_url(l)
-
-# Kill the broker after all tests
-MiniTest.after_run do
-  Process.kill(:TERM, $broker.pid) if $broker
-end

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/ruby/examples/testme
----------------------------------------------------------------------
diff --git a/ruby/examples/testme b/ruby/examples/testme
new file mode 100755
index 0000000..5c0c59d
--- /dev/null
+++ b/ruby/examples/testme
@@ -0,0 +1,110 @@
+#!/usr/bin/ruby
+#
+# 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.
+#
+
+require 'minitest/autorun'
+require 'qpid_proton'
+require 'socket'
+require 'rbconfig'
+
+begin
+  MiniTest::Test
+rescue NameError                # For older versions of MiniTest
+  MiniTest::Test = MiniTest::Unit::TestCase
+end
+
+def listening_port(s)
+  /Listening on ([0-9]+)/.match(s)[1]
+end
+
+def listening_url(s)
+  ":#{listening_port s}"
+end
+
+class ExampleTest < MiniTest::Test
+
+  def run_script(*args)
+    return IO.popen([ RbConfig.ruby ] + args.map { |a| a.to_s })
+  end
+
+  def assert_output(want, *args)
+    assert_equal(want.strip, run_script(*args).read.strip)
+  end
+
+  def test_helloworld
+    assert_output("Hello world!", "helloworld.rb", $url, "examples")
+  end
+
+  def test_client_server
+    want =  <<EOS
+-> 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.
+EOS
+    server = run_script("server.rb", $url, "examples")
+    assert_output(want.strip, "client.rb", $url, "examples")
+  ensure
+    Process.kill :TERM, server.pid if server
+  end
+
+  def test_send_recv
+    assert_output("All 10 messages confirmed!", "simple_send.rb", $url, 
"examples")
+    want = (0..9).reduce("") { |x,y| x << "Received: sequence #{y}\n" }
+    assert_output(want.strip, "simple_recv.rb", $url, "examples")
+  end
+
+  def test_ssl_send_recv
+    skip 'SSL not available' unless Qpid::Proton::SSL.present?
+    out = run_script("ssl_send.rb", $url, "examples").read.strip
+    assert_match(/Connection secured with "...*\"\nAll 10 messages 
confirmed!/, out)
+    want = (0..9).reduce("") { |x,y| x << "Received: sequence #{y}\n" }
+    assert_output(want.strip, "simple_recv.rb", $url, "examples")
+  end
+
+  def test_direct_recv
+    p = run_script("direct_recv.rb", ":0", "examples")
+    url = listening_url(p.readline) # Wait till ready
+    assert_output("All 10 messages confirmed!", "simple_send.rb", url, 
"examples")
+    want = (0..9).reduce("") { |x,y| x << "Received: sequence #{y}\n" }
+    assert_equal(want.strip, p.read.strip)
+  end
+
+  def test_direct_send
+    p = run_script("direct_send.rb", ":0", "examples")
+    url = listening_url(p.readline) # Wait till ready
+    want = (0..9).reduce("") { |x,y| x << "Received: sequence #{y}\n" }
+    assert_output(want.strip, "simple_recv.rb", url, "examples")
+    assert_equal("All 10 messages confirmed!", p.read.strip)
+  end
+end
+
+# Start the broker before all tests.
+$broker = IO.popen([RbConfig.ruby, 'broker.rb', ":0"])
+l = $broker.readline
+$url = listening_url(l)
+
+# Kill the broker after all tests
+MiniTest.after_run do
+  Process.kill(:TERM, $broker.pid) if $broker
+end

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/runtime_check.cmake
----------------------------------------------------------------------
diff --git a/runtime_check.cmake b/runtime_check.cmake
deleted file mode 100644
index e1d76c3..0000000
--- a/runtime_check.cmake
+++ /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.
-#
-
-# Configuration for code analysis tools: runtime checking and coverage.
-
-# Any test that needs runtime checks should use TEST_EXE_PREFIX and TEST_ENV.
-# Normally they are set as a result of the RUNTIME_CHECK value,
-# but can be set directly for unsupported tools or unusual flags
-# e.g. -DTEST_EXE_PREFIX=rr or -DTEST_EXE_PREFIX="valgrind --tool=massif"
-
-set(TEST_EXE_PREFIX "" CACHE STRING "Prefix for test executable command line")
-set(TEST_WRAP_PREFIX "" CACHE STRING "Prefix for interpreter tests (e.g. 
python, ruby) that load proton as an extension")
-set(TEST_ENV "" CACHE STRING "Extra environment for tests: 
name1=value1;name2=value2")
-mark_as_advanced(TEST_EXE_PREFIX TEST_WRAP_PREFIX TEST_ENV)
-
-# Check for valgrind
-find_program(VALGRIND_EXECUTABLE valgrind DOC "location of valgrind program")
-set(VALGRIND_SUPPRESSIONS "${CMAKE_SOURCE_DIR}/tests/valgrind.supp" CACHE 
STRING "Suppressions file for valgrind")
-set(VALGRIND_COMMON_ARGS "--error-exitcode=42 --quiet 
--suppressions=${VALGRIND_SUPPRESSIONS}")
-mark_as_advanced(VALGRIND_EXECUTABLE VALGRIND_SUPPRESSIONS 
VALGRIND_COMMON_ARGS)
-
-# Check for compiler sanitizers
-if((CMAKE_C_COMPILER_ID MATCHES "GNU"
-      AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.8)
-    OR (CMAKE_C_COMPILER_ID MATCHES "Clang"
-      AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.1))
-  set(HAS_SANITIZERS TRUE)
-endif()
-
-# Valid values for RUNTIME_CHECK
-set(runtime_checks OFF asan tsan memcheck helgrind)
-
-# Set the default
-if(NOT CMAKE_BUILD_TYPE MATCHES "Coverage" AND VALGRIND_EXECUTABLE)
-  set(RUNTIME_CHECK_DEFAULT "memcheck")
-endif()
-
-# Deprecated options to enable runtime checks
-macro(deprecated_enable_check old new doc)
-  option(${old} ${doc} OFF)
-  if (${old})
-    message("WARNING: option ${old} is deprecated, use RUNTIME_CHECK=${new} 
instead")
-    set(RUNTIME_CHECK_DEFAULT ${new})
-  endif()
-endmacro()
-deprecated_enable_check(ENABLE_VALGRIND memcheck "Use valgrind to detect 
run-time problems")
-deprecated_enable_check(ENABLE_SANITIZERS asan "Compile with memory sanitizers 
(asan, ubsan)")
-deprecated_enable_check(ENABLE_TSAN tsan "Compile with thread sanitizer 
(tsan)")
-
-set(RUNTIME_CHECK ${RUNTIME_CHECK_DEFAULT} CACHE string "Enable runtime 
checks. Valid values: ${runtime_checks}")
-
-if(CMAKE_BUILD_TYPE MATCHES "Coverage" AND RUNTIME_CHECK)
-  message(FATAL_ERROR "Cannot set RUNTIME_CHECK with 
CMAKE_BUILD_TYPE=Coverage")
-endif()
-
-macro(assert_has_sanitizers)
-  if(NOT HAS_SANITIZERS)
-    message(FATAL_ERROR "compiler sanitizers are not available")
-  endif()
-endmacro()
-
-macro(assert_has_valgrind)
-  if(NOT VALGRIND_EXECUTABLE)
-    message(FATAL_ERROR "valgrind is not available")
-  endif()
-endmacro()
-
-if(RUNTIME_CHECK STREQUAL "memcheck")
-  assert_has_valgrind()
-  message(STATUS "Runtime memory checker: valgrind memcheck")
-  set(TEST_EXE_PREFIX "${VALGRIND_EXECUTABLE} --tool=memcheck 
--leak-check=full ${VALGRIND_COMMON_ARGS}")
-  # FIXME aconway 2018-09-06: NO TEST_WRAP_PREFIX, need --trace-children + 
many suppressions
-
-elseif(RUNTIME_CHECK STREQUAL "helgrind")
-  assert_has_valgrind()
-  message(STATUS "Runtime race checker: valgrind helgrind")
-  set(TEST_EXE_PREFIX "${VALGRIND_EXECUTABLE} --tool=helgrind 
${VALGRIND_COMMON_ARGS}")
-  # FIXME aconway 2018-09-06: NO TEST_WRAP_PREFIX, need --trace-children + 
many suppressions
-
-elseif(RUNTIME_CHECK STREQUAL "asan")
-  assert_has_sanitizers()
-  message(STATUS "Runtime memory checker: gcc/clang memory sanitizers")
-  set(SANITIZE_FLAGS "-g -fno-omit-frame-pointer -fsanitize=address,undefined")
-  set(TEST_WRAP_PREFIX "${CMAKE_SOURCE_DIR}/tests/preload_asan.sh 
$<TARGET_FILE:qpid-proton-core>")
-
-elseif(RUNTIME_CHECK STREQUAL "tsan")
-  assert_has_sanitizers()
-  message(STATUS "Runtime race checker: gcc/clang thread sanitizer")
-  set(SANITIZE_FLAGS "-g -fno-omit-frame-pointer -fsanitize=thread")
-
-elseif(RUNTIME_CHECK)
-  message(FATAL_ERROR "'RUNTIME_CHECK=${RUNTIME_CHECK}' is invalid, valid 
values: ${runtime_checks}")
-endif()
-
-if(SANITIZE_FLAGS)
-  set(ENABLE_UNDEFINED_ERROR OFF CACHE BOOL "Disabled for sanitizers" FORCE)
-  string(APPEND CMAKE_C_FLAGS " ${SANITIZE_FLAGS}")
-  string(APPEND CMAKE_CXX_FLAGS "${SANITIZE_FLAGS}")
-endif()
-
-if(TEST_EXE_PREFIX)
-  # Add TEST_EXE_PREFIX to TEST_ENV so test runner scripts can use it.
-  list(APPEND TEST_ENV "TEST_EXE_PREFIX=${TEST_EXE_PREFIX}")
-  # Make a CMake-list form of TEST_EXE_PREFIX for add_test() commands
-  separate_arguments(TEST_EXE_PREFIX_CMD UNIX_COMMAND "${TEST_EXE_PREFIX}")
-endif()
-separate_arguments(TEST_WRAP_PREFIX_CMD UNIX_COMMAND "${TEST_WRAP_PREFIX}")

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/tests/py/test_subprocess.py
----------------------------------------------------------------------
diff --git a/tests/py/test_subprocess.py b/tests/py/test_subprocess.py
index 1c7d2b9..512123f 100644
--- a/tests/py/test_subprocess.py
+++ b/tests/py/test_subprocess.py
@@ -33,7 +33,7 @@ class TestProcessError(Exception):
 
 class Popen(subprocess.Popen):
     """
-    Adds TEST_EXE_PREFIX to the command and checks stderr for runtime checker 
output.
+    Add TEST_EXE_PREFIX to the command, check stderr for runtime checker 
output.
     In a 'with' statement it runs check_wait() on exit from the block, or
     check_kill() if initialized with kill_me=True
     """
@@ -43,11 +43,13 @@ class Popen(subprocess.Popen):
         Takes all args and kwargs of subprocess.Popen except stdout, stderr, 
universal_newlines
         kill_me=True runs check_kill() in __exit__() instead of check_wait()
         """
-        self.cmd = args[0]
         self.on_exit = self.check_kill if kwargs.pop('kill_me', False) else 
self.check_wait
         self.errfile = tempfile.NamedTemporaryFile(delete=False)
         kwargs.update({'universal_newlines': True, 'stdout': PIPE, 'stderr': 
self.errfile})
-        args = ((os.environ.get("TEST_EXE_PREFIX", "").split() + args[0]),) + 
args[1:]
+        prefix = os.environ.get("TEST_EXE_PREFIX")
+        if prefix:
+            args = [prefix.split() + args[0]] + list(args[1:])
+        self.cmd = args[0]
         super(Popen, self).__init__(*args, **kwargs)
 
     def check_wait(self):
@@ -75,7 +77,7 @@ class Popen(subprocess.Popen):
         line = self.stdout.readline()
         match = re.search(pattern, line)
         if not match:
-            raise Exception("%s: can't find '%s' in '%s'" % (self.cmd, 
pattern, line))
+            raise TestProcessError(self, "can't find '%s' in '%s'" % (pattern, 
line))
         return match
 
     @property

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/tests/runtime_check.cmake
----------------------------------------------------------------------
diff --git a/tests/runtime_check.cmake b/tests/runtime_check.cmake
new file mode 100644
index 0000000..e1d76c3
--- /dev/null
+++ b/tests/runtime_check.cmake
@@ -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.
+#
+
+# Configuration for code analysis tools: runtime checking and coverage.
+
+# Any test that needs runtime checks should use TEST_EXE_PREFIX and TEST_ENV.
+# Normally they are set as a result of the RUNTIME_CHECK value,
+# but can be set directly for unsupported tools or unusual flags
+# e.g. -DTEST_EXE_PREFIX=rr or -DTEST_EXE_PREFIX="valgrind --tool=massif"
+
+set(TEST_EXE_PREFIX "" CACHE STRING "Prefix for test executable command line")
+set(TEST_WRAP_PREFIX "" CACHE STRING "Prefix for interpreter tests (e.g. 
python, ruby) that load proton as an extension")
+set(TEST_ENV "" CACHE STRING "Extra environment for tests: 
name1=value1;name2=value2")
+mark_as_advanced(TEST_EXE_PREFIX TEST_WRAP_PREFIX TEST_ENV)
+
+# Check for valgrind
+find_program(VALGRIND_EXECUTABLE valgrind DOC "location of valgrind program")
+set(VALGRIND_SUPPRESSIONS "${CMAKE_SOURCE_DIR}/tests/valgrind.supp" CACHE 
STRING "Suppressions file for valgrind")
+set(VALGRIND_COMMON_ARGS "--error-exitcode=42 --quiet 
--suppressions=${VALGRIND_SUPPRESSIONS}")
+mark_as_advanced(VALGRIND_EXECUTABLE VALGRIND_SUPPRESSIONS 
VALGRIND_COMMON_ARGS)
+
+# Check for compiler sanitizers
+if((CMAKE_C_COMPILER_ID MATCHES "GNU"
+      AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.8)
+    OR (CMAKE_C_COMPILER_ID MATCHES "Clang"
+      AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.1))
+  set(HAS_SANITIZERS TRUE)
+endif()
+
+# Valid values for RUNTIME_CHECK
+set(runtime_checks OFF asan tsan memcheck helgrind)
+
+# Set the default
+if(NOT CMAKE_BUILD_TYPE MATCHES "Coverage" AND VALGRIND_EXECUTABLE)
+  set(RUNTIME_CHECK_DEFAULT "memcheck")
+endif()
+
+# Deprecated options to enable runtime checks
+macro(deprecated_enable_check old new doc)
+  option(${old} ${doc} OFF)
+  if (${old})
+    message("WARNING: option ${old} is deprecated, use RUNTIME_CHECK=${new} 
instead")
+    set(RUNTIME_CHECK_DEFAULT ${new})
+  endif()
+endmacro()
+deprecated_enable_check(ENABLE_VALGRIND memcheck "Use valgrind to detect 
run-time problems")
+deprecated_enable_check(ENABLE_SANITIZERS asan "Compile with memory sanitizers 
(asan, ubsan)")
+deprecated_enable_check(ENABLE_TSAN tsan "Compile with thread sanitizer 
(tsan)")
+
+set(RUNTIME_CHECK ${RUNTIME_CHECK_DEFAULT} CACHE string "Enable runtime 
checks. Valid values: ${runtime_checks}")
+
+if(CMAKE_BUILD_TYPE MATCHES "Coverage" AND RUNTIME_CHECK)
+  message(FATAL_ERROR "Cannot set RUNTIME_CHECK with 
CMAKE_BUILD_TYPE=Coverage")
+endif()
+
+macro(assert_has_sanitizers)
+  if(NOT HAS_SANITIZERS)
+    message(FATAL_ERROR "compiler sanitizers are not available")
+  endif()
+endmacro()
+
+macro(assert_has_valgrind)
+  if(NOT VALGRIND_EXECUTABLE)
+    message(FATAL_ERROR "valgrind is not available")
+  endif()
+endmacro()
+
+if(RUNTIME_CHECK STREQUAL "memcheck")
+  assert_has_valgrind()
+  message(STATUS "Runtime memory checker: valgrind memcheck")
+  set(TEST_EXE_PREFIX "${VALGRIND_EXECUTABLE} --tool=memcheck 
--leak-check=full ${VALGRIND_COMMON_ARGS}")
+  # FIXME aconway 2018-09-06: NO TEST_WRAP_PREFIX, need --trace-children + 
many suppressions
+
+elseif(RUNTIME_CHECK STREQUAL "helgrind")
+  assert_has_valgrind()
+  message(STATUS "Runtime race checker: valgrind helgrind")
+  set(TEST_EXE_PREFIX "${VALGRIND_EXECUTABLE} --tool=helgrind 
${VALGRIND_COMMON_ARGS}")
+  # FIXME aconway 2018-09-06: NO TEST_WRAP_PREFIX, need --trace-children + 
many suppressions
+
+elseif(RUNTIME_CHECK STREQUAL "asan")
+  assert_has_sanitizers()
+  message(STATUS "Runtime memory checker: gcc/clang memory sanitizers")
+  set(SANITIZE_FLAGS "-g -fno-omit-frame-pointer -fsanitize=address,undefined")
+  set(TEST_WRAP_PREFIX "${CMAKE_SOURCE_DIR}/tests/preload_asan.sh 
$<TARGET_FILE:qpid-proton-core>")
+
+elseif(RUNTIME_CHECK STREQUAL "tsan")
+  assert_has_sanitizers()
+  message(STATUS "Runtime race checker: gcc/clang thread sanitizer")
+  set(SANITIZE_FLAGS "-g -fno-omit-frame-pointer -fsanitize=thread")
+
+elseif(RUNTIME_CHECK)
+  message(FATAL_ERROR "'RUNTIME_CHECK=${RUNTIME_CHECK}' is invalid, valid 
values: ${runtime_checks}")
+endif()
+
+if(SANITIZE_FLAGS)
+  set(ENABLE_UNDEFINED_ERROR OFF CACHE BOOL "Disabled for sanitizers" FORCE)
+  string(APPEND CMAKE_C_FLAGS " ${SANITIZE_FLAGS}")
+  string(APPEND CMAKE_CXX_FLAGS "${SANITIZE_FLAGS}")
+endif()
+
+if(TEST_EXE_PREFIX)
+  # Add TEST_EXE_PREFIX to TEST_ENV so test runner scripts can use it.
+  list(APPEND TEST_ENV "TEST_EXE_PREFIX=${TEST_EXE_PREFIX}")
+  # Make a CMake-list form of TEST_EXE_PREFIX for add_test() commands
+  separate_arguments(TEST_EXE_PREFIX_CMD UNIX_COMMAND "${TEST_EXE_PREFIX}")
+endif()
+separate_arguments(TEST_WRAP_PREFIX_CMD UNIX_COMMAND "${TEST_WRAP_PREFIX}")

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/tests/share/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/tests/share/CMakeLists.txt b/tests/share/CMakeLists.txt
new file mode 100644
index 0000000..a50c0e9
--- /dev/null
+++ b/tests/share/CMakeLists.txt
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+
+cmake_minimum_required(VERSION 2.8.12)
+
+project(ProtonExamples)
+include(CTest)
+enable_testing()
+include("tests/runtime_check.cmake")
+
+# ind example sub-directories that contain "CMakeLists.txt" or "testme"
+set(ex_dir "${CMAKE_SOURCE_DIR}/examples")
+file(GLOB subs ${ex_dir}/*)
+foreach(dir ${subs})
+  get_filename_component(ex "${dir}" NAME)
+  if(EXISTS ${dir}/CMakeLists.txt)
+    # Has CMakeLists.txt to define example tests.
+    add_subdirectory(${dir})
+  elseif(EXISTS ${dir}/testme)
+    # Has a "testme" script to run example tests.
+    add_test(
+      NAME ${ex}-example-tests
+      COMMAND ${dir}/testme
+      WORKING_DIRECTORY ${dir})
+  endif()
+ endforeach()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/tests/share/README.txt
----------------------------------------------------------------------
diff --git a/tests/share/README.txt b/tests/share/README.txt
new file mode 100644
index 0000000..f7864b6
--- /dev/null
+++ b/tests/share/README.txt
@@ -0,0 +1,3 @@
+This directory is for files that should be installed at the top level
+of the INSTALL_PREFIX/share/proton-VERSION directory to support
+installed testing.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/393f8a67/tests/share/examples-README.md
----------------------------------------------------------------------
diff --git a/tests/share/examples-README.md b/tests/share/examples-README.md
new file mode 100644
index 0000000..6f7404c
--- /dev/null
+++ b/tests/share/examples-README.md
@@ -0,0 +1,20 @@
+Verifying the examples 
+======================
+
+If you have installed support for self-testing a proton installation you can
+automatically run and verify the examples.
+
+To build C, C++ tests and run all tests:
+
+    cd TEMP-BUILD-DIR
+    cmake INSTALL-PREFIX/share/proton-VERSION/examples
+    make
+    ctest
+
+To run an individual test that does not require CMake, (e.g. ruby):
+
+    cd  INSTALL-PREFIX/share/proton-VERSION/examples/ruby
+    ./testme
+
+Some testme scripts accept additional arguments (e.g. -v for verbose)
+


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

Reply via email to