You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2018/11/02 20:46:30 UTC
[10/50] qpid-proton git commit: PROTON-1798: cmake runtime-check
improvements
PROTON-1798: cmake runtime-check improvements
Usage notes:
- new CMake variable: RUNTIME_CHECK, choose from [memcheck helgrind asan tsan OFF]
- defaults to 'memcheck' if available, else OFF
- old ENABLE_ variables for valgrind/sanitizers are deprecated
- example_test scripts check for stderr output including from killed processes
Implementation details:
- moved all runtime-check setup code to seprate runtime-check.cmake
- tool-agnostic internal CMake variables for running tests
- removed all valgrind-specific code outside of runtime-check.cmake
- example_test.py check stderr as well as exit status to catch broker issues.
NOTE: asan,tsan not yet working for python/ruby bindings, they are disabled in
san builds. See tests/preload_asan.sh for current status of the work.
NOTE: Some python soak tests for obscure messenger features were removed, they
have faulty start-up timing logic and can fail under valgrind. We can restore
them if needed but we'll need to fix the -X feature of msgr-recv to report ready
only after connections are remote open.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/27edd9ac
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/27edd9ac
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/27edd9ac
Branch: refs/heads/go1
Commit: 27edd9aca3b2b1078089ceaa2a387f0016ac6f0a
Parents: 7885bd3
Author: Alan Conway <ac...@redhat.com>
Authored: Fri Sep 7 13:20:42 2018 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Mon Sep 10 15:41:24 2018 -0400
----------------------------------------------------------------------
CMakeLists.txt | 71 +++------------
c/examples/CMakeLists.txt | 7 +-
c/examples/example_test.py | 58 +++++-------
c/tests/CMakeLists.txt | 4 +-
c/tests/fuzz/CMakeLists.txt | 2 +-
c/tests/threaderciser.supp | 18 ----
c/tests/threaderciser.tsupp | 5 -
cpp/CMakeLists.txt | 2 +-
cpp/examples/CMakeLists.txt | 14 ++-
cpp/examples/broker.cpp | 4 +-
cpp/examples/example_test.py | 42 ++-------
misc/config.sh.in | 6 --
python/CMakeLists.txt | 8 +-
python/tests/proton_tests/common.py | 35 +------
python/tests/proton_tests/soak.py | 83 ++---------------
python/tests/proton_tests/ssl.py | 33 -------
python/tox.ini.in | 2 +-
ruby/CMakeLists.txt | 8 +-
runtime_check.cmake | 123 +++++++++++++++++++++++++
scripts/env.py | 5 -
tests/preload_asan.sh | 51 +++++++++++
tests/py/test_subprocess.py | 105 +++++++++++++++++++++
tests/valgrind.supp | 151 +++++++++++++++++++++++++++++++
23 files changed, 517 insertions(+), 320 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 560dc05..105f22e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,9 @@ find_package (CyrusSASL)
enable_testing ()
+# Set up runtime checks (valgrind, sanitizers etc.)
+include(runtime_check.cmake)
+
## Variables used across components
set (PN_ENV_SCRIPT "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/env.py")
@@ -188,23 +191,6 @@ if (CMAKE_C_COMPILER_ID MATCHES "Clang")
set (CXX_WARNING_FLAGS "${COMPILE_WARNING_FLAGS} -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-float-equal -Wno-padded -Wno-sign-conversion -Wno-switch-enum -Wno-weak-vtables -Wno-exit-time-destructors -Wno-global-constructors -Wno-shorten-64-to-32 -Wno-documentation -Wno-documentation-unknown-command -Wno-old-style-cast -Wno-missing-noreturn")
endif()
-# Sanitizer flags apply to to both GNU and clang, C and C++
-if(ENABLE_SANITIZERS)
- set(SANITIZE_FLAGS "-g -fno-omit-frame-pointer -fsanitize=address -fsanitize=leak -fsanitize=undefined")
-endif()
-if(ENABLE_TSAN)
- set(SANITIZE_FLAGS "-g -fno-omit-frame-pointer -fsanitize=thread")
-endif()
-if (SANITIZE_FLAGS)
- mark_as_advanced(SANITIZE_FLAGS)
- if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZE_FLAGS}")
- endif()
- if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZE_FLAGS}")
- endif()
-endif()
-
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
if (NOT CMAKE_OSX_ARCHITECTURES)
set(CMAKE_OSX_ARCHITECTURES "x86_64")
@@ -300,41 +286,6 @@ endforeach()
set (PROTON_SHARE ${SHARE_INSTALL_DIR}/proton-${PN_VERSION})
# End of variables used during install
-# Can't do valgrind and coverage at athe same time - coverage takes precedence
-if (CMAKE_BUILD_TYPE MATCHES "Coverage")
- message(STATUS "Building for coverage analysis; no run-time error detection")
-else ()
- find_program(VALGRIND_EXECUTABLE valgrind DOC "Location of the valgrind program")
- mark_as_advanced (VALGRIND_EXECUTABLE)
-
- option(ENABLE_VALGRIND "Use valgrind to detect run-time problems" ON)
- if (ENABLE_VALGRIND)
- if (VALGRIND_EXECUTABLE)
- set (VALGRIND_SUPPRESSIONS ${CMAKE_SOURCE_DIR}/c/tests/valgrind.supp CACHE STRING "Default valgrind suppressions")
- set (VALGRIND_OPTIONS "--error-exitcode=42 --quiet --leak-check=full --trace-children=yes" CACHE STRING "Default valgrind options")
- mark_as_advanced(VALGRIND_SUPPRESSIONS VALGRIND_OPTIONS)
- set (VALGRIND_ENV "VALGRIND=${VALGRIND_EXECUTABLE}" "VALGRIND_ARGS=${VALGRIND_OPTIONS} --suppressions=${VALGRIND_SUPPRESSIONS}")
- separate_arguments(VALGRIND_OPTIONS_LIST UNIX_COMMAND ${VALGRIND_OPTIONS})
- set (memcheck-cmd ${VALGRIND_EXECUTABLE} ${VALGRIND_OPTIONS_LIST} "--suppressions=${VALGRIND_SUPPRESSIONS}")
- set (racecheck-cmd ${VALGRIND_EXECUTABLE} --tool=helgrind --error-exitcode=42 --quiet)
- else ()
- message(STATUS "Can't locate the valgrind command; no run-time error detection")
- endif ()
- endif ()
-endif ()
-
-# Options to enable sanitizing compile flags. Compile flags are set in c/CMakeLists.txt
-option(ENABLE_SANITIZERS "Compile with sanitizers (ASan, UBSan, TSan); incompatible with Valgrind" OFF)
-option(ENABLE_TSAN "Compile with Thread Sanitizer (TSan); incompatible with Valgrind" OFF)
-if (ENABLE_SANITIZERS OR ENABLE_TSAN)
- set(DISABLE ENABLE_VALGRIND ENABLE_UNDEFINED_ERROR BUILD_GO)
- message(STATUS "Building with sanitizers; disables ${DISABLE}")
- foreach(d ${DISABLE})
- set(${d} OFF CACHE BOOL "Disabled to run sanitizers" FORCE)
- endforeach()
- unset(VALGRIND_ENV)
-endif()
-
# Set result to a native search path - used by examples and binding tests.
# args after result are directories or search paths.
macro(set_search_path result)
@@ -379,11 +330,11 @@ endif()
find_program(GO_EXE go)
mark_as_advanced(GO_EXE)
if (GO_EXE)
- if(WIN32)
+ set (DEFAULT_GO ON)
+ if(WIN32 OR RUNTIME_CHECK)
# Go on windows requires gcc tool chain
+ # Go does not work with C-based runtime checkers.
set (DEFAULT_GO OFF)
- else()
- set (DEFAULT_GO ON)
endif()
endif (GO_EXE)
@@ -405,15 +356,17 @@ if(SWIG_FOUND)
# Prerequisites for Python wrapper:
find_package (PythonLibs ${PYTHON_VERSION_STRING} EXACT)
- if (PYTHONLIBS_FOUND)
+ # TODO aconway 2018-09-07: get python binding tests working with sanitizers
+ if (PYTHONLIBS_FOUND AND NOT SANITIZE_FLAGS)
set (DEFAULT_PYTHON ON)
- endif (PYTHONLIBS_FOUND)
+ endif ()
# Prerequisites for Ruby:
find_package(Ruby)
- if (RUBY_FOUND)
+ # TODO aconway 2018-09-07: get ruby binding tests working with sanitizers
+ if (RUBY_FOUND AND NOT SANITIZE_FLAGS)
set (DEFAULT_RUBY ON)
- endif (RUBY_FOUND)
+ endif ()
endif()
# To kick-start a build with just a few bindings enabled by default, e.g. ruby and go:
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/c/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/c/examples/CMakeLists.txt b/c/examples/CMakeLists.txt
index 6128f62..b04e444 100644
--- a/c/examples/CMakeLists.txt
+++ b/c/examples/CMakeLists.txt
@@ -45,6 +45,9 @@ endif()
add_test(
NAME c-example-tests
- COMMAND ${PN_ENV_SCRIPT} "PATH=${test_path}" ${VALGRIND_ENV} --
- ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v
+ 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})
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/c/examples/example_test.py
----------------------------------------------------------------------
diff --git a/c/examples/example_test.py b/c/examples/example_test.py
index 1834989..35a8993 100644
--- a/c/examples/example_test.py
+++ b/c/examples/example_test.py
@@ -20,31 +20,14 @@
# Run the C examples and verify that they behave as expected.
# Example executables must be in PATH
-import unittest, sys, time, re
+import unittest
-import subprocess
+from test_subprocess import Popen, TestProcessError, check_output
-class Server(subprocess.Popen):
+class Server(Popen):
def __init__(self, *args, **kwargs):
- self.kill_me = kwargs.pop('kill_me', False)
- kwargs.update({'universal_newlines': True,
- 'stdout': subprocess.PIPE})
super(Server, self).__init__(*args, **kwargs)
-
- def __enter__(self):
- line = self.stdout.readline()
- self.port = re.search("listening on ([0-9]+)$", line).group(1)
- return self
-
- def __exit__(self, *args):
- if self.kill_me:
- self.kill()
- self.stdout.close() # Doesn't get closed if killed
- self.wait()
-
-def check_output(*args, **kwargs):
- kwargs.update({'universal_newlines': True})
- return subprocess.check_output(*args, **kwargs)
+ self.port = self.expect("listening on ([0-9]+)$").group(1)
MESSAGES=10
@@ -64,6 +47,10 @@ class ExampleTest(unittest.TestCase):
"""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:
@@ -73,20 +60,21 @@ class ExampleTest(unittest.TestCase):
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(), self.runex("receive", b.port))
+ self.assertMultiLineEqual(receive_expect(), r.communicate()[0])
def test_send_direct(self):
"""Send to direct server"""
- with Server(["direct", "", "0"]) as d:
- self.assertEqual(send_expect(), self.runex("send", d.port))
- self.assertMultiLineEqual(receive_expect(), d.communicate()[0])
+ 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"""
- with Server(["direct", "", "0"]) as d:
- self.assertMultiLineEqual(receive_expect(), self.runex("receive", d.port))
- self.assertEqual("10 messages sent and acknowledged\n", d.communicate()[0])
+ 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"""
@@ -101,13 +89,13 @@ class ExampleTest(unittest.TestCase):
def test_send_abort_direct(self):
"""Send aborted messages to the direct server"""
- with Server(["direct", "", "0", "examples", "20"]) as d:
- self.assertEqual(send_expect(), self.runex("send", d.port))
- self.assertEqual(send_abort_expect(), self.runex("send-abort", d.port))
- self.assertEqual(send_expect(), self.runex("send", d.port))
- expect = receive_expect_messages() + "Message aborted\n"*MESSAGES + receive_expect_messages()+receive_expect_total(20)
- self.maxDiff = None
- self.assertMultiLineEqual(expect, d.communicate()[0])
+ 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"""
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/c/tests/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/c/tests/CMakeLists.txt b/c/tests/CMakeLists.txt
index 87dfdb6..a4bfb67 100644
--- a/c/tests/CMakeLists.txt
+++ b/c/tests/CMakeLists.txt
@@ -32,7 +32,7 @@ macro (pn_add_c_test_nolib test)
if (BUILD_WITH_CXX)
set_source_files_properties (${ARGN} PROPERTIES LANGUAGE CXX)
endif (BUILD_WITH_CXX)
- add_test(NAME ${test} COMMAND ${test_env} ${memcheck-cmd} $<TARGET_FILE:${test}>)
+ add_test(NAME ${test} COMMAND ${test_env} ${TEST_EXE_PREFIX_CMD} $<TARGET_FILE:${test}>)
endmacro (pn_add_c_test_nolib)
# Add test with qpid-proton-core linked
@@ -58,7 +58,7 @@ if(HAS_PROACTOR)
pn_add_c_test (c-proactor-tests proactor.c)
target_link_libraries (c-proactor-tests qpid-proton-proactor)
- # TODO Enable by default when races are cleared up
+ # TODO Enable by default when races and xcode problems are cleared up
option(THREADERCISER "Run the threaderciser concurrency tests" OFF)
if (THREADERCISER)
pn_add_c_test(c-threaderciser threaderciser.c)
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/c/tests/fuzz/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/c/tests/fuzz/CMakeLists.txt b/c/tests/fuzz/CMakeLists.txt
index 19825b6..5d4187d 100644
--- a/c/tests/fuzz/CMakeLists.txt
+++ b/c/tests/fuzz/CMakeLists.txt
@@ -37,7 +37,7 @@ macro (pn_add_fuzz_test test)
if (FUZZ_REGRESSION_TESTS)
# StandaloneFuzzTargetMain cannot walk directory trees
file(GLOB_RECURSE files ${CMAKE_CURRENT_SOURCE_DIR}/${test}/*)
- add_test (NAME ${test} COMMAND ${memcheck-cmd} $<TARGET_FILE:${test}> ${files})
+ add_test (NAME ${test} COMMAND ${TEST_EXE_PREFIX_CMD} $<TARGET_FILE:${test}> ${files})
else ()
add_test (NAME ${test} COMMAND $<TARGET_FILE:${test}> -runs=1 ${CMAKE_CURRENT_SOURCE_DIR}/${test}>)
endif ()
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/c/tests/threaderciser.supp
----------------------------------------------------------------------
diff --git a/c/tests/threaderciser.supp b/c/tests/threaderciser.supp
deleted file mode 100644
index d14ff61..0000000
--- a/c/tests/threaderciser.supp
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- IGNORE: benign race in pni_log_enabled
- Helgrind:Race
- fun:pni_log_enabled
-}
-
-{
- IGNORE: NSS library poking around in its own data segment upsets helgrind
- Helgrind:Race
- fun:strpbrk
- fun:_nss_files_parse_servent
-}
-{
- IGNORE: NSS library poking around in its own text segment upsets helgrind
- Helgrind:Race
- fun:*
- fun:_nss_files_getservbyname_r
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/c/tests/threaderciser.tsupp
----------------------------------------------------------------------
diff --git a/c/tests/threaderciser.tsupp b/c/tests/threaderciser.tsupp
deleted file mode 100644
index 18ceb23..0000000
--- a/c/tests/threaderciser.tsupp
+++ /dev/null
@@ -1,5 +0,0 @@
-# TSAN suppressions for threaderciser
-
-# Benign race in pni_log_enabled
-race:pni_log_enabled
-
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 0dcede2..a06e67d 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -242,7 +242,7 @@ macro(add_cpp_test test)
"PATH=$<TARGET_FILE_DIR:qpid-proton>"
$<TARGET_FILE:${test}> ${ARGN})
else ()
- add_test (NAME cpp-${test} COMMAND ${memcheck-cmd} $<TARGET_FILE:${test}> ${ARGN})
+ add_test (NAME cpp-${test} COMMAND ${TEST_EXE_PREFIX_CMD} $<TARGET_FILE:${test}> ${ARGN})
endif ()
endmacro(add_cpp_test)
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/cpp/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/cpp/examples/CMakeLists.txt b/cpp/examples/CMakeLists.txt
index 18d922e..ba18d83 100644
--- a/cpp/examples/CMakeLists.txt
+++ b/cpp/examples/CMakeLists.txt
@@ -104,7 +104,7 @@ if(HAS_ENOUGH_CPP11)
endif()
# Add a test with the correct environment to find test executables and valgrind.
-macro(add_cpp_test name)
+macro(add_cpp_example_test name)
if(WIN32)
set(test_path "$<TARGET_FILE_DIR:broker>;$<TARGET_FILE_DIR:qpid-proton>;$<TARGET_FILE_DIR:qpid-proton-cpp>")
else(WIN32)
@@ -112,13 +112,17 @@ macro(add_cpp_test name)
endif(WIN32)
add_test(
NAME ${name}
- COMMAND ${PN_ENV_SCRIPT} "PATH=${test_path}" ${VALGRIND_ENV}
- "HAS_CPP11=$<$<BOOL:${HAS_ENOUGH_CPP11}>:1>" -- ${ARGN}
+ COMMAND ${PN_ENV_SCRIPT}
+ "PATH=${test_path}"
+ "PYTHONPATH=${CMAKE_SOURCE_DIR}/tests/py"
+ "HAS_CPP11=$<$<BOOL:${HAS_ENOUGH_CPP11}>:1>"
+ ${TEST_ENV} --
+ ${ARGN}
)
endmacro()
-add_cpp_test(cpp-example-container ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleTest)
+add_cpp_example_test(cpp-example-container ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleTest)
if (NOT SSL_IMPL STREQUAL none)
-add_cpp_test(cpp-example-container-ssl ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleSSLTest)
+add_cpp_example_test(cpp-example-container-ssl ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleSSLTest)
endif()
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/cpp/examples/broker.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/broker.cpp b/cpp/examples/broker.cpp
index d45309e..b15ac39 100644
--- a/cpp/examples/broker.cpp
+++ b/cpp/examples/broker.cpp
@@ -355,7 +355,7 @@ public:
}
void on_error(const proton::error_condition& e) OVERRIDE {
- std::cerr << "error: " << e.what() << std::endl;
+ std::cout << "protocol error: " << e.what() << std::endl;
}
// The container calls on_transport_close() last.
@@ -429,7 +429,7 @@ int main(int argc, char **argv) {
} catch (const example::bad_option& e) {
std::cout << opts << std::endl << e.what() << std::endl;
} catch (const std::exception& e) {
- std::cerr << "broker shutdown: " << e.what() << std::endl;
+ std::cout << "broker shutdown: " << e.what() << std::endl;
}
return 1;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/cpp/examples/example_test.py
----------------------------------------------------------------------
diff --git a/cpp/examples/example_test.py b/cpp/examples/example_test.py
index edcde27..38a9a6e 100644
--- a/cpp/examples/example_test.py
+++ b/cpp/examples/example_test.py
@@ -20,40 +20,21 @@
# Run the C++ examples and verify that they behave as expected.
# Example executables must be in PATH
-import unittest, sys, time, re, shutil, os
+import unittest, sys, shutil, os
+from test_subprocess import Popen, TestProcessError, check_output
from os.path import dirname
from string import Template
-import subprocess
-
-class Server(subprocess.Popen):
+class Server(Popen):
+ """A process that prints 'listening on <port>' to stdout"""
def __init__(self, *args, **kwargs):
- self.port = None
- self.kill_me = kwargs.pop('kill_me', False)
- kwargs.update({'universal_newlines': True,
- 'stdout': subprocess.PIPE})
super(Server, self).__init__(*args, **kwargs)
-
- def __enter__(self):
- return self
-
- def __exit__(self, *args):
- if self.kill_me:
- self.kill()
- self.stdout.close() # Doesn't get closed if killed
- self.wait()
+ self.port = self.expect("listening on ([0-9]+)$").group(1)
@property
def addr(self):
- if not self.port:
- line = self.stdout.readline()
- self.port = re.search("listening on ([0-9]+)$", line).group(1)
return ":%s/example" % self.port
-def check_output(*args, **kwargs):
- kwargs.update({'universal_newlines': True})
- return subprocess.check_output(*args, **kwargs)
-
def _cyrusSetup(conf_dir):
"""Write out simple SASL config.tests
"""
@@ -77,12 +58,9 @@ mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS
# Globally initialize Cyrus SASL configuration
_cyrusSetup('sasl-conf')
-def wait_listening(p):
- return re.search(b"listening on ([0-9]+)$", p.stdout.readline()).group(1)
-
class Broker(Server):
- def __init__(self):
- super(Broker, self).__init__(["broker", "-a", "//:0"], kill_me=True)
+ 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.
@@ -104,7 +82,7 @@ class ContainerExampleTest(unittest.TestCase):
self.assertMultiLineEqual(recv_expect(), check_output(["simple_recv", "-a", Broker.addr]))
def test_simple_recv_send(self):
- recv = Server(["simple_recv", "-a", Broker.addr])
+ 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])
@@ -119,8 +97,8 @@ class ContainerExampleTest(unittest.TestCase):
self.assertMultiLineEqual("all messages confirmed\n", send.communicate()[0])
def test_request_response(self):
- with Server(["server", Broker.addr, "example"], kill_me=True) as server:
- self.assertIn("connected to", server.stdout.readline())
+ 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):
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/misc/config.sh.in
----------------------------------------------------------------------
diff --git a/misc/config.sh.in b/misc/config.sh.in
index a61c757..dd23602 100755
--- a/misc/config.sh.in
+++ b/misc/config.sh.in
@@ -52,12 +52,6 @@ export LD_LIBRARY_PATH="$(merge_paths $PROTON_BUILD $LD_LIBRARY_PATH)"
# Test applications
export PATH="$(merge_paths $PATH $PROTON_BUILD/c/tools $PROTON_HOME/python/tests)"
-# Can the test harness use valgrind?
-if [[ -x "$(type -p valgrind)" && "@ENABLE_VALGRIND@" == "ON" ]] ; then
- export VALGRIND=$(type -p valgrind)
- export VALGRIND_ARGS="@VALGRIND_OPTIONS@"
-fi
-
# Can the test harness use saslpasswd2?
if [[ -x "$(type -p saslpasswd2)" ]] ; then
export SASLPASSWD=$(type -p saslpasswd2)
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/python/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index d63ab96..181128c 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -208,8 +208,8 @@ add_test (NAME python-test
COMMAND ${PN_ENV_SCRIPT}
"PATH=${py_path}" "PYTHONPATH=${py_pythonpath}"
"SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
- ${VALGRIND_ENV}
- ${PYTHON_EXECUTABLE} -- ${python_coverage_options} "${py_tests}/proton-test")
+ ${TEST_ENV}
+ ${TEST_WRAP_PREFIX_CMD} ${PYTHON_EXECUTABLE} -- ${python_coverage_options} "${py_tests}/proton-test")
set_tests_properties(python-test PROPERTIES PASS_REGULAR_EXPRESSION "Totals: .* 0 failed")
check_python_module("tox" TOX_MODULE_FOUND)
@@ -237,8 +237,8 @@ else ()
"PATH=${py_path}"
"SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
"SWIG=${SWIG_EXECUTABLE}"
- ${VALGRIND_ENV} --
- ${PYTHON_EXECUTABLE} -m tox)
+ ${TEST_ENV} --
+ ${TEST_WRAP_PREFIX_CMD} ${PYTHON_EXECUTABLE} -m tox)
set_tests_properties(python-tox-test
PROPERTIES
PASS_REGULAR_EXPRESSION "Totals: .* ignored, 0 failed"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/python/tests/proton_tests/common.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/common.py b/python/tests/proton_tests/common.py
index fd4decc..a56a2c0 100644
--- a/python/tests/proton_tests/common.py
+++ b/python/tests/proton_tests/common.py
@@ -281,7 +281,7 @@ class MessengerApp(object):
del cmd[0:1]
cmd.insert(0, foundfile)
cmd.insert(0, sys.executable)
- self._process = Popen(cmd, stdout=PIPE, stderr=STDOUT,
+ self._process = Popen(cmd, stdout=PIPE,
bufsize=4096, universal_newlines=True)
except OSError:
e = sys.exc_info()[1]
@@ -425,7 +425,8 @@ class MessengerReceiver(MessengerApp):
# command string?
def _build_command(self):
- self._cmdline = self._command
+ self._cmdline = os.environ.get("TEST_EXE_PREFIX", "").split()
+ self._cmdline += self._command
self._do_common_options()
self._cmdline += ["-X", "READY"]
assert self.subscriptions, "Missing subscriptions, required for receiver!"
@@ -468,47 +469,17 @@ class MessengerSenderC(MessengerSender):
MessengerSender.__init__(self)
self._command = ["msgr-send"]
-def setup_valgrind(self):
- if "VALGRIND" not in os.environ:
- raise Skipped("Skipping test - $VALGRIND not set.")
- super(type(self), self).__init__()
- self._command = [os.environ["VALGRIND"]] + os.environ["VALGRIND_ARGS"].split(' ') + self._command
-
-class MessengerSenderValgrind(MessengerSenderC):
- """ Run the C sender under Valgrind
- """
- def __init__(self, suppressions=None):
- setup_valgrind(self)
-
class MessengerReceiverC(MessengerReceiver):
def __init__(self):
MessengerReceiver.__init__(self)
self._command = ["msgr-recv"]
-class MessengerReceiverValgrind(MessengerReceiverC):
- """ Run the C receiver under Valgrind
- """
- def __init__(self, suppressions=None):
- setup_valgrind(self)
-
class ReactorSenderC(MessengerSender):
def __init__(self):
MessengerSender.__init__(self)
self._command = ["reactor-send"]
-class ReactorSenderValgrind(ReactorSenderC):
- """ Run the C sender under Valgrind
- """
- def __init__(self, suppressions=None):
- setup_valgrind(self)
-
class ReactorReceiverC(MessengerReceiver):
def __init__(self):
MessengerReceiver.__init__(self)
self._command = ["reactor-recv"]
-
-class ReactorReceiverValgrind(ReactorReceiverC):
- """ Run the C receiver under Valgrind
- """
- def __init__(self, suppressions=None):
- setup_valgrind(self)
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/python/tests/proton_tests/soak.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/soak.py b/python/tests/proton_tests/soak.py
index 5e103fd..e015db5 100644
--- a/python/tests/proton_tests/soak.py
+++ b/python/tests/proton_tests/soak.py
@@ -24,9 +24,7 @@ import os
from .common import Test, Skipped, free_tcp_ports, \
MessengerReceiverC, MessengerSenderC, \
- MessengerReceiverValgrind, MessengerSenderValgrind, \
ReactorReceiverC, ReactorSenderC, \
- ReactorReceiverValgrind, ReactorSenderValgrind, \
isSSLPresent
#
@@ -192,52 +190,14 @@ class MessengerTests(AppTests):
self._do_test(iterations)
- def _do_relay_test(self, receiver, relay, sender, domain="amqp"):
- """ Send N messages to a receiver, which replies to each and forwards
- each of them to different receiver.
- Parameters:
- iterations - repeat the senders this many times
- target_count - # targets to send to
- send_count = # messages sent to each target
- send_batch - wait for replies after this many messages sent
- forward_count - forward to this many targets
- """
- iterations = self.iterations
- send_count = self.send_count
- target_count = self.target_count
- send_batch = self.send_batch
- forward_count = self.forward_count
-
- send_total = send_count * target_count
- receive_total = send_total * iterations
-
- port = free_tcp_ports()[0]
-
- receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port)]
- receiver.receive_count = receive_total
- receiver.send_reply = True
- # forward to 'relay' - uses two links
- # ## THIS FAILS:
- # receiver.forwards = ["amqp://Relay/%d" % j for j in range(forward_count)]
- receiver.forwards = ["%s://Relay" % domain]
- receiver.timeout = MessengerTests._timeout
- self.receivers.append( receiver )
-
- relay.subscriptions = ["%s://0.0.0.0:%s" % (domain, port)]
- relay.name = "Relay"
- relay.receive_count = receive_total
- relay.timeout = MessengerTests._timeout
- self.receivers.append( relay )
-
- # send to 'receiver'
- sender.targets = ["%s://0.0.0.0:%s/X%dY" % (domain, port, j) for j in range(target_count)]
- sender.send_count = send_total
- sender.get_reply = True
- sender.timeout = MessengerTests._timeout
- self.senders.append( sender )
-
- self._do_test(iterations)
-
+ # Removed messenger "relay" tests. The test start-up is faulty:
+ # msgr-recv prints it's -X ready message when it starts to open a
+ # connection but it does not wait for the remote open. The relay
+ # tests depends on mapping a container name from an incoming
+ # connection. They can fail under if the sender starts before the
+ # connection is complete (esp. valgrind with SSL connections) We
+ # could fix the tests but since messenger is deprecated it does
+ # not seem worthwhile.
def _do_star_topology_test(self, r_factory, s_factory, domain="amqp"):
"""
@@ -291,10 +251,6 @@ class MessengerTests(AppTests):
self._ssl_check()
self._do_oneway_test(MessengerReceiverC(), MessengerSenderC(), "amqps")
- def test_oneway_valgrind(self):
- self.valgrind_test()
- self._do_oneway_test(MessengerReceiverValgrind(), MessengerSenderValgrind())
-
def test_echo_C(self):
self._do_echo_test(MessengerReceiverC(), MessengerSenderC())
@@ -302,21 +258,6 @@ class MessengerTests(AppTests):
self._ssl_check()
self._do_echo_test(MessengerReceiverC(), MessengerSenderC(), "amqps")
- def test_echo_valgrind(self):
- self.valgrind_test()
- self._do_echo_test(MessengerReceiverValgrind(), MessengerSenderValgrind())
-
- def test_relay_C(self):
- self._do_relay_test(MessengerReceiverC(), MessengerReceiverC(), MessengerSenderC())
-
- def test_relay_C_SSL(self):
- self._ssl_check()
- self._do_relay_test(MessengerReceiverC(), MessengerReceiverC(), MessengerSenderC(), "amqps")
-
- def test_relay_valgrind(self):
- self.valgrind_test()
- self._do_relay_test(MessengerReceiverValgrind(), MessengerReceiverValgrind(), MessengerSenderValgrind())
-
def test_star_topology_C(self):
self._do_star_topology_test( MessengerReceiverC, MessengerSenderC )
@@ -324,13 +265,5 @@ class MessengerTests(AppTests):
self._ssl_check()
self._do_star_topology_test( MessengerReceiverC, MessengerSenderC, "amqps" )
- def test_star_topology_valgrind(self):
- self.valgrind_test()
- self._do_star_topology_test( MessengerReceiverValgrind, MessengerSenderValgrind )
-
def test_oneway_reactor(self):
self._do_oneway_test(ReactorReceiverC(), ReactorSenderC())
-
- def test_oneway_reactor_valgrind(self):
- self.valgrind_test()
- self._do_oneway_test(ReactorReceiverValgrind(), ReactorSenderValgrind())
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/python/tests/proton_tests/ssl.py
----------------------------------------------------------------------
diff --git a/python/tests/proton_tests/ssl.py b/python/tests/proton_tests/ssl.py
index fcc3795..9419292 100644
--- a/python/tests/proton_tests/ssl.py
+++ b/python/tests/proton_tests/ssl.py
@@ -882,39 +882,6 @@ class SslTest(common.Test):
receiver.wait()
assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline())
- def DISABLED_test_defaults_valgrind(self):
- """ Run valgrind over a simple SSL connection (no certificates)
- """
- # the openssl libraries produce far too many valgrind errors to be
- # useful. AFAIK, there is no way to wriate a valgrind suppression
- # expression that will ignore all errors from a given library.
- # Until we can, skip this test.
- port = common.free_tcp_ports()[0]
-
- receiver = common.MessengerReceiverValgrind()
- receiver.subscriptions = ["amqps://~127.0.0.1:%s" % port]
- receiver.receive_count = 1
- receiver.timeout = self.timeout
- receiver.start()
-
- sender = common.MessengerSenderValgrind()
- sender.targets = ["amqps://127.0.0.1:%s/X" % port]
- sender.send_count = 1
- sender.timeout = self.timeout
- sender.start()
- sender.wait()
- assert sender.status() == 0, "Command '%s' failed" % str(sender.cmdline())
-
- receiver.wait()
- assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline())
-
- # self.server_domain.set_credentials(self._testpath("client-certificate.pem"),
- # self._testpath("client-private-key.pem"),
- # "client-password")
-
- # self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
- # self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER )
-
def test_singleton(self):
"""Verify that only a single instance of SSL can exist per Transport"""
transport = Transport()
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/python/tox.ini.in
----------------------------------------------------------------------
diff --git a/python/tox.ini.in b/python/tox.ini.in
index c514078..ec4a77d 100644
--- a/python/tox.ini.in
+++ b/python/tox.ini.in
@@ -13,7 +13,7 @@ passenv =
PKG_CONFIG_PATH
CFLAGS
SASLPASSWD
- VALGRIND
+ TEST_EXE_PREFIX
commands =
@CMAKE_SOURCE_DIR@/python/tests/proton-test '{posargs:--ignore-file=@CMAKE_SOURCE_DIR@/python/tests/tox-blacklist}'
deps =
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/ruby/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/ruby/CMakeLists.txt b/ruby/CMakeLists.txt
index e205250..eb99907 100644
--- a/ruby/CMakeLists.txt
+++ b/ruby/CMakeLists.txt
@@ -125,14 +125,18 @@ to_native_path("${bin};${c_lib_dir};$ENV{PATH}" PATH)
execute_process(COMMAND ${RUBY_EXECUTABLE} -r minitest -e ""
RESULT_VARIABLE result OUTPUT_QUIET ERROR_QUIET)
if (result EQUAL 0) # Have minitest
- set(test_env ${PN_ENV_SCRIPT} -- "PATH=${PATH}" "RUBYLIB=${RUBYLIB}" "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}")
+ set(test_env ${PN_ENV_SCRIPT} --
+ "PATH=${PATH}"
+ "RUBYLIB=${RUBYLIB}"
+ "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
+ ${TEST_ENV})
macro(add_ruby_test script)
get_filename_component(name ${script} NAME_WE)
string(REPLACE "_" "-" name "ruby-${name}")
add_test(
NAME ${name}
- COMMAND ${test_env} ${RUBY_EXECUTABLE} ${script} -v
+ COMMAND ${test_env} ${TEST_WRAP_PREFIX_CMD} ${RUBY_EXECUTABLE} ${script} -v
${ARGN})
endmacro()
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/runtime_check.cmake
----------------------------------------------------------------------
diff --git a/runtime_check.cmake b/runtime_check.cmake
new file mode 100644
index 0000000..e1d76c3
--- /dev/null
+++ b/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/27edd9ac/scripts/env.py
----------------------------------------------------------------------
diff --git a/scripts/env.py b/scripts/env.py
index 04fa8bb..14df6d1 100644
--- a/scripts/env.py
+++ b/scripts/env.py
@@ -58,11 +58,6 @@ def main(argv=None):
if len(args) == 0 or len(args[0]) == 0:
raise Exception("Error: syntax error in command arguments")
- if new_env.get("VALGRIND") and new_env.get("VALGRIND_ALL"):
- # Python generates a lot of possibly-lost errors that are not errors, don't show them.
- args = [new_env.get("VALGRIND"), "--show-reachable=no", "--show-possibly-lost=no",
- "--error-exitcode=42"] + args
-
p = subprocess.Popen(args, env=new_env)
return p.wait()
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/tests/preload_asan.sh
----------------------------------------------------------------------
diff --git a/tests/preload_asan.sh b/tests/preload_asan.sh
new file mode 100755
index 0000000..e4928f9
--- /dev/null
+++ b/tests/preload_asan.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# 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.
+#
+
+if test $# -lt 2; then
+ echo <<EOF
+usage: $0 LIB EXE [args ...]
+Get the libasan linked to LIB and preload it to run `EXE args ...`
+EOF
+fi
+
+LIB=$1; shift
+EXE=$2
+
+case $EXE in
+ *ruby*|*.rb|*python*|*.py)
+ # ruby has spurious leaks and causes asan errors.
+ #
+ # python tests have many leaks that may be real, but need to be
+ # analysed & fixed or suppressed before turning this on
+
+ # Disable link order check to run with limited sanitizing
+ # Still seeing problems.
+ export ASAN_OPTIONS=verify_asan_link_order=0
+ ;;
+ *)
+ # Preload the asan library linked to LIB. Note we need to
+ # check the actual linkage, there may be multiple asan lib
+ # versions installed and we must use the same one.
+ libasan=$(ldd $LIB | awk "/(libasan\\.so[.0-9]*)/ { print \$1 }")
+ export LD_PRELOAD="$libasan:$LD_PRELOAD"
+ ;;
+esac
+
+exec "$@"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/tests/py/test_subprocess.py
----------------------------------------------------------------------
diff --git a/tests/py/test_subprocess.py b/tests/py/test_subprocess.py
new file mode 100644
index 0000000..1c7d2b9
--- /dev/null
+++ b/tests/py/test_subprocess.py
@@ -0,0 +1,105 @@
+#
+# 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
+#
+
+# Extends the subprocess module to use runtime checkers, and report stderr output.
+
+import subprocess, re, os, tempfile
+
+from subprocess import PIPE
+
+class TestProcessError(Exception):
+ def __init__(self, proc, what, output=None):
+ self.output = output
+ sep = "\n%s stderr(%s) %s\n" %("_" * 32, proc.pid, "_" * 32)
+ error = sep + proc.error + sep if proc.error else ""
+ super(TestProcessError, self).__init__("%s pid=%s exit=%s: %s%s" % (
+ proc.cmd, proc.pid, proc.returncode, what, error))
+
+class Popen(subprocess.Popen):
+ """
+ Adds TEST_EXE_PREFIX to the command and checks 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
+ """
+
+ def __init__(self, *args, **kwargs):
+ """
+ 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:]
+ super(Popen, self).__init__(*args, **kwargs)
+
+ def check_wait(self):
+ if self.wait() or self.error:
+ raise TestProcessError(self, "check_wait")
+
+ def communicate(self, *args, **kwargs):
+ result = super(Popen, self).communicate(*args, **kwargs)
+ if self.returncode or self.error:
+ raise TestProcessError(self, "check_communicate", result[0])
+ return result
+
+ def check_kill(self):
+ """Raise if process has already exited, kill and raise if self.error is not empty"""
+ if self.poll() is None:
+ self.kill()
+ self.wait()
+ self.stdout.close() # Doesn't get closed if killed
+ if self.error:
+ raise TestProcessError(self, "check_kill found error output")
+ else:
+ raise TestProcessError(self, "check_kill process not running")
+
+ def expect(self, pattern):
+ 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))
+ return match
+
+ @property
+ def error(self):
+ """Return stderr as string, may only be used after process has terminated."""
+ assert(self.poll is not None)
+ if not hasattr(self, "_error"):
+ self.errfile.close() # Not auto-deleted
+ with open(self.errfile.name) as f: # Re-open to read
+ self._error = f.read().strip()
+ os.unlink(self.errfile.name)
+ return self._error
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.on_exit()
+
+def check_output(*args, **kwargs):
+ return Popen(*args, **kwargs).communicate()[0]
+
+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)
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/27edd9ac/tests/valgrind.supp
----------------------------------------------------------------------
diff --git a/tests/valgrind.supp b/tests/valgrind.supp
new file mode 100644
index 0000000..3fee095
--- /dev/null
+++ b/tests/valgrind.supp
@@ -0,0 +1,151 @@
+{
+ SSL does a number of uninitialized accesses (expected) 1
+ Memcheck:Cond
+ fun:BN_bin2bn
+ obj:*
+ obj:*
+}
+
+{
+ SSL does a number of uninitialized accesses (expected) 2
+ Memcheck:Cond
+ fun:BN_num_bits_word
+ fun:BN_num_bits
+}
+
+{
+ SSL does a number of uninitialized accesses (expected) 3
+ Memcheck:Value8
+ fun:BN_num_bits_word
+ fun:BN_num_bits
+ fun:BN_mod_exp_mont_consttime
+ obj:*
+ fun:ssl3_ctx_ctrl
+}
+
+{
+ SSL does a number of uninitialized accesses (expected) 4
+ Memcheck:Value8
+ fun:BN_mod_exp_mont_consttime
+ obj:*
+ fun:ssl3_ctx_ctrl
+}
+
+{
+ SSL does a number of uninitialized accesses (FreeBSD version)
+ Memcheck:Value8
+ fun:BN_num_bits_word
+ fun:BN_num_bits
+ fun:BN_mod_exp_mont_consttime
+ fun:BN_mod_exp_mont
+ obj:*libcrypto.so*
+ fun:ssl3_ctx_ctrl
+}
+
+{
+ SSL does a number of uninitialized accesses (FreeBSD version)
+ Memcheck:Value8
+ fun:BN_mod_exp_mont_consttime
+ fun:BN_mod_exp_mont
+ obj:*libcrypto.so*
+ fun:ssl3_ctx_ctrl
+}
+
+{
+ SSL does a number of uninitialized accesses (expected) 5
+ Memcheck:Value4
+ fun:BN_mod_exp_mont_consttime
+ fun:BN_mod_exp_mont
+ obj:*
+ obj:*
+}
+
+{
+ SSL does a number of uninitialized accesses (expected) 6
+ Memcheck:Value4
+ fun:BN_num_bits_word
+ fun:BN_mod_exp_mont_consttime
+ fun:BN_mod_exp_mont
+ obj:*
+ obj:*
+}
+
+{
+ SSL does a number of uninitialized accesses (expected) 7
+ Memcheck:Cond
+ fun:ASN1_STRING_set
+ fun:ASN1_mbstring_ncopy
+ fun:ASN1_mbstring_copy
+}
+
+{
+ Since we can never safely uninitialize SSL, allow this
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_realloc
+ fun:CRYPTO_realloc
+ fun:lh_insert
+ obj:/lib64/libcrypto.so.0.9.8e
+ fun:ERR_load_strings
+ fun:ERR_load_X509V3_strings
+ fun:ERR_load_crypto_strings
+ fun:SSL_load_error_strings
+}
+
+{
+ Since we can never safely uninitialize SSL, allow this
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_malloc
+ fun:CRYPTO_malloc
+ fun:lh_new
+ fun:OBJ_NAME_init
+ fun:OBJ_NAME_add
+ fun:EVP_add_cipher
+ fun:SSL_library_init
+}
+
+{
+ Since we can never safely uninitialize SSL, allow this
+ Memcheck:Leak
+ fun:malloc
+ obj:*
+ fun:CRYPTO_malloc
+}
+
+{
+ Known memory leak in cyrus-sasl (fixed in 2.1.26)
+ Memcheck:Leak
+ fun:malloc
+ fun:*
+ fun:sasl_config_init
+ fun:sasl_server_init
+}
+
+{
+ Known bug in glibc which tries to free ipv6 related static when getaddrinfo used
+ Memcheck:Free
+ fun:free
+ fun:__libc_freeres
+ fun:_vgnU_freeres
+ fun:__run_exit_handlers
+ fun:exit
+}
+
+{
+ Benign race in pni_log_enabled
+ Helgrind:Race
+ fun:pni_log_enabled
+}
+
+{
+ NSS library poking around in its own data segment upsets helgrind
+ Helgrind:Race
+ fun:strpbrk
+ fun:_nss_files_parse_servent
+}
+
+{
+ NSS library poking around in its own text segment upsets helgrind
+ Helgrind:Race
+ fun:*
+ fun:_nss_files_getservbyname_r
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org