qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From acon...@apache.org
Subject [39/50] [abbrv] qpid-proton git commit: PROTON-1495: move examples/exampletest.py to tools/py/proctest.py
Date Fri, 09 Jun 2017 01:26:02 GMT
PROTON-1495: move examples/exampletest.py to tools/py/proctest.py

It is not an example but part of our test framework.
Want to use it for non-example tests as well.


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

Branch: refs/heads/go1
Commit: 08505261f4008c43b2399cb4a72bd887bbadd7df
Parents: d480600
Author: Alan Conway <aconway@redhat.com>
Authored: Fri Jun 2 09:33:43 2017 -0400
Committer: Alan Conway <aconway@redhat.com>
Committed: Wed Jun 7 09:59:23 2017 -0400

----------------------------------------------------------------------
 config.sh.in                        |   2 +-
 examples/CMakeLists.txt             |   4 +-
 examples/c/proactor/example_test.py |   4 +-
 examples/cpp/example_test.py        |   4 +-
 examples/exampletest.py             | 193 -----------------------------
 tools/py/proctest.py                | 204 +++++++++++++++++++++++++++++++
 6 files changed, 211 insertions(+), 200 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/08505261/config.sh.in
----------------------------------------------------------------------
diff --git a/config.sh.in b/config.sh.in
index 72d4ea9..d9debd3 100755
--- a/config.sh.in
+++ b/config.sh.in
@@ -39,7 +39,7 @@ RUBY_BINDINGS=$PROTON_BINDINGS/ruby
 PERL_BINDINGS=$PROTON_BINDINGS/perl
 
 # Python
-COMMON_PYPATH=$PROTON_HOME/tests/python:$PROTON_HOME/proton-c/bindings/python:$PROTON_HOME/examples
+COMMON_PYPATH=$PROTON_HOME/tests/python:$PROTON_HOME/proton-c/bindings/python:$PROTON_HOME/tools/py
 export PYTHONPATH=$COMMON_PYPATH:$PYTHON_BINDINGS
 
 # PHP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/08505261/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 4d744d2..8a8327a 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -29,8 +29,8 @@ macro(set_search_path result)  # args after result are directories or search
pat
   file(TO_NATIVE_PATH "${${result}}" ${result}) # native slash separators
 endmacro()
 
-# Some non-python examples use exampletest.py to drive their self-tests.
-set_search_path(EXAMPLE_PYTHONPATH "${CMAKE_CURRENT_SOURCE_DIR}" "$ENV{PYTHON_PATH}")
+# Add the tools directory for the 'proctest' module
+set_search_path(EXAMPLE_PYTHONPATH "${CMAKE_SOURCE_DIR}/tools/py" "$ENV{PYTHON_PATH}")
 set(EXAMPLE_ENV "PYTHONPATH=${EXAMPLE_PYTHONPATH}")
 
 add_subdirectory(c)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/08505261/examples/c/proactor/example_test.py
----------------------------------------------------------------------
diff --git a/examples/c/proactor/example_test.py b/examples/c/proactor/example_test.py
index 38f7fc8..02bb1fd 100644
--- a/examples/c/proactor/example_test.py
+++ b/examples/c/proactor/example_test.py
@@ -20,7 +20,7 @@
 # This is a test script to run the examples and verify that they behave as expected.
 
 import unittest, sys, time
-from exampletest import *
+from proctest import *
 
 def python_cmd(name):
     dir = os.path.dirname(__file__)
@@ -49,7 +49,7 @@ class Broker(object):
                 raise ProcError(b, "broker crash")
             b.kill()
 
-class CExampleTest(ExampleTestCase):
+class CExampleTest(ProcTestCase):
 
     def test_send_receive(self):
         """Send first then receive"""

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/08505261/examples/cpp/example_test.py
----------------------------------------------------------------------
diff --git a/examples/cpp/example_test.py b/examples/cpp/example_test.py
index 5773142..0ae929c 100644
--- a/examples/cpp/example_test.py
+++ b/examples/cpp/example_test.py
@@ -21,7 +21,7 @@
 
 import unittest
 import os, sys, socket, time, re, inspect
-from exampletest import *
+from proctest import *
 from  random import randrange
 from subprocess import Popen, PIPE, STDOUT, call
 from copy import copy
@@ -82,7 +82,7 @@ def ensureCanTestExtendedSASL():
     raise Skipped("Can't Test Extended SASL: Couldn't create auth db")
 
 
-class BrokerTestCase(ExampleTestCase):
+class BrokerTestCase(ProcTestCase):
     """
     ExampleTest that starts a broker in setUpClass and kills it in tearDownClass.
     Subclasses must set `broker_exe` class variable with the name of the broker executable.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/08505261/examples/exampletest.py
----------------------------------------------------------------------
diff --git a/examples/exampletest.py b/examples/exampletest.py
deleted file mode 100644
index 5c53616..0000000
--- a/examples/exampletest.py
+++ /dev/null
@@ -1,193 +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
-#
-
-# A test library to make it easy to run unittest tests that start,
-# monitor, and report output from sub-processes. In particular
-# it helps with starting processes that listen on random ports.
-
-import unittest
-import os, sys, socket, time, re, inspect, errno, threading
-from  random import randrange
-from subprocess import Popen, PIPE, STDOUT
-from copy import copy
-import platform
-from os.path import dirname as dirname
-
-DEFAULT_TIMEOUT=10
-
-class TestPort(object):
-    """Get an unused port using bind(0) and SO_REUSEADDR and hold it till close()"""
-    def __init__(self):
-        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        self.sock.bind(('127.0.0.1', 0)) # Testing exampless is local only
-        self.host, self.port = socket.getnameinfo(self.sock.getsockname(), 0)
-        self.addr = "%s:%s" % (self.host, self.port)
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, *args):
-        self.close()
-
-    def close(self):
-        self.sock.close()
-
-class ProcError(Exception):
-    """An exception that captures failed process output"""
-    def __init__(self, proc, what="bad exit status"):
-        out = proc.out.strip()
-        if out:
-            out = "\nvvvvvvvvvvvvvvvv\n%s\n^^^^^^^^^^^^^^^^\n" % out
-        else:
-            out = ", no output)"
-        super(Exception, self, ).__init__(
-            "%s %s, code=%s%s" % (proc.args, what, getattr(proc, 'returncode', 'noreturn'),
out))
-
-class NotFoundError(ProcError):
-    pass
-
-class Proc(Popen):
-    """A example process that stores its stdout and can scan it for a 'ready' pattern'"""
-
-    if "VALGRIND" in os.environ and os.environ["VALGRIND"]:
-        vg_args = [os.environ["VALGRIND"], "--error-exitcode=42", "--quiet", "--leak-check=full"]
-    else:
-        vg_args = []
-
-    @property
-    def out(self):
-        self._out.seek(0)
-        # Normalize line endings, os.tmpfile() opens in binary mode.
-        return self._out.read().replace('\r\n','\n').replace('\r','\n')
-
-    def __init__(self, args, skip_valgrind=False, **kwargs):
-        """Start an example process"""
-        args = list(args)
-        if skip_valgrind:
-            self.args = args
-        else:
-            self.args = self.vg_args + args
-        self.kwargs = kwargs
-        self._out = os.tmpfile()
-        try:
-            Popen.__init__(self, self.args, stdout=self._out, stderr=STDOUT, **kwargs)
-        except OSError, e:
-            if e.errno == errno.ENOENT:
-                raise NotFoundError(self, str(e))
-            raise ProcError(self, str(e))
-        except Exception, e:
-            raise ProcError(self, str(e))
-
-    def kill(self):
-        try:
-            if self.poll() is None:
-                Popen.kill(self)
-        except:
-            pass                # Already exited.
-        return self.out
-
-    def wait_exit(self, timeout=DEFAULT_TIMEOUT, expect=0):
-        """Wait for process to exit, return output. Raise ProcError  on failure."""
-        t = threading.Thread(target=self.wait)
-        t.start()
-        t.join(timeout)
-        if self.poll() is None:      # Still running
-            self.kill()
-            raise ProcError(self, "still running after %ss" % timeout)
-        if expect is not None and self.poll() != expect:
-            raise ProcError(self)
-        return self.out
-
-    def wait_re(self, regexp, timeout=DEFAULT_TIMEOUT):
-        """
-        Wait for regexp to appear in the output, returns the re.search match result.
-        The target process should flush() important output to ensure it appears.
-        """
-        if timeout:
-            deadline = time.time() + timeout
-        while timeout is None or time.time() < deadline:
-            match = re.search(regexp, self.out)
-            if match:
-                return match
-            time.sleep(0.01)    # Not very efficient
-        raise ProcError(self, "gave up waiting for '%s' after %ss" % (regexp, timeout))
-
-def _tc_missing(attr):
-    return not hasattr(unittest.TestCase, attr)
-
-class TestCase(unittest.TestCase):
-    """
-    Roughly provides setUpClass() and tearDownClass() and other features missing
-    in python 2.6. If subclasses override setUp() or tearDown() they *must*
-    call the superclass.
-    """
-
-    if _tc_missing('setUpClass') and _tc_missing('tearDownClass'):
-
-        @classmethod
-        def setUpClass(cls):
-            pass
-
-        @classmethod
-        def tearDownClass(cls):
-            pass
-
-        def setUp(self):
-            super(TestCase, self).setUp()
-            cls = type(self)
-            if not hasattr(cls, '_setup_class_count'): # First time
-                def is_test(m):
-                    return inspect.ismethod(m) and m.__name__.startswith('test_')
-                cls._setup_class_count = len(inspect.getmembers(cls, predicate=is_test))
-                cls.setUpClass()
-
-        def tearDown(self):
-            self.assertTrue(self._setup_class_count > 0)
-            self._setup_class_count -=  1
-            if self._setup_class_count == 0:
-                type(self).tearDownClass()
-            super(TestCase, self).tearDown()
-
-    if _tc_missing('assertIn'):
-        def assertIn(self, a, b):
-            self.assertTrue(a in b, "%r not in %r" % (a, b))
-
-    if _tc_missing('assertMultiLineEqual'):
-        def assertMultiLineEqual(self, a, b):
-            self.assertEqual(a, b)
-
-class ExampleTestCase(TestCase):
-    """TestCase that manages started processes"""
-    def setUp(self):
-        super(ExampleTestCase, self).setUp()
-        self.procs = []
-
-    def tearDown(self):
-        for p in self.procs:
-            p.kill()
-        super(ExampleTestCase, self).tearDown()
-
-    def proc(self, *args, **kwargs):
-        p = Proc(*args, **kwargs)
-        self.procs.append(p)
-        return p
-
-if __name__ == "__main__":
-    unittest.main()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/08505261/tools/py/proctest.py
----------------------------------------------------------------------
diff --git a/tools/py/proctest.py b/tools/py/proctest.py
new file mode 100644
index 0000000..ba83c7d
--- /dev/null
+++ b/tools/py/proctest.py
@@ -0,0 +1,204 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License
+#
+
+"""Unit test library to simplify tests that start, monitor, check and report
+output from sub-processes. Provides safe port allocation for processes that
+listen on a port. Allows executables to be run under a debugging tool like
+valgrind.
+"""
+
+import unittest
+import os, sys, socket, time, re, inspect, errno, threading
+from  random import randrange
+from subprocess import Popen, PIPE, STDOUT
+from copy import copy
+import platform
+from os.path import dirname as dirname
+
+DEFAULT_TIMEOUT=10
+
+class TestPort(object):
+    """Get an unused port using bind(0) and SO_REUSEADDR and hold it till close()
+    Can be used as `with TestPort() as tp:` Provides tp.host, tp.port and tp.addr
+    (a "host:port" string)
+    """
+    def __init__(self):
+        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        self.sock.bind(('127.0.0.1', 0)) # Testing exampless is local only
+        self.host, self.port = socket.getnameinfo(self.sock.getsockname(), 0)
+        self.addr = "%s:%s" % (self.host, self.port)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args):
+        self.close()
+
+    def close(self):
+        self.sock.close()
+
+class ProcError(Exception):
+    """An exception that displays failed process output"""
+    def __init__(self, proc, what="bad exit status"):
+        self.out = proc.out.strip()
+        if self.out:
+            msgtail = "\nvvvvvvvvvvvvvvvv\n%s\n^^^^^^^^^^^^^^^^\n" % self.out
+        else:
+            msgtail = ", no output"
+        super(Exception, self, ).__init__(
+            "%s %s, code=%s%s" % (proc.args, what, getattr(proc, 'returncode', 'noreturn'),
msgtail))
+
+class NotFoundError(ProcError):
+    pass
+
+class Proc(Popen):
+    """Subclass of suprocess.Popen that stores its output and can scan it for a
+    'ready' pattern' Use self.out to access output (combined stdout and stderr).
+    You can't set the Popen stdout and stderr arguments, they will be overwritten.
+    """
+
+    if "VALGRIND" in os.environ and os.environ["VALGRIND"]:
+        vg_args = [os.environ["VALGRIND"], "--error-exitcode=42", "--quiet", "--leak-check=full"]
+    else:
+        vg_args = []
+
+    @property
+    def out(self):
+        self._out.seek(0)
+        # Normalize line endings, os.tmpfile() opens in binary mode.
+        return self._out.read().replace('\r\n','\n').replace('\r','\n')
+
+    def __init__(self, args, skip_valgrind=False, **kwargs):
+        """Start an example process"""
+        args = list(args)
+        if skip_valgrind:
+            self.args = args
+        else:
+            self.args = self.vg_args + args
+        self.kwargs = kwargs
+        self._out = os.tmpfile()
+        try:
+            Popen.__init__(self, self.args, stdout=self._out, stderr=STDOUT, **kwargs)
+        except OSError, e:
+            if e.errno == errno.ENOENT:
+                raise NotFoundError(self, str(e))
+            raise ProcError(self, str(e))
+        except Exception, e:
+            raise ProcError(self, str(e))
+
+    def kill(self):
+        try:
+            if self.poll() is None:
+                Popen.kill(self)
+        except:
+            pass                # Already exited.
+        return self.out
+
+    def wait_exit(self, timeout=DEFAULT_TIMEOUT, expect=0):
+        """Wait for process to exit, return output. Raise ProcError  on failure."""
+        t = threading.Thread(target=self.wait)
+        t.start()
+        t.join(timeout)
+        if self.poll() is None:      # Still running
+            self.kill()
+            raise ProcError(self, "still running after %ss" % timeout)
+        if expect is not None and self.poll() != expect:
+            raise ProcError(self)
+        return self.out
+
+    def wait_re(self, regexp, timeout=DEFAULT_TIMEOUT):
+        """
+        Wait for regexp to appear in the output, returns the re.search match result.
+        The target process should flush() important output to ensure it appears.
+        """
+        if timeout:
+            deadline = time.time() + timeout
+        while timeout is None or time.time() < deadline:
+            match = re.search(regexp, self.out)
+            if match:
+                return match
+            if self.poll() is not None:
+                raise ProcError(self, "process exited while waiting for '%s'" % (regexp))
+            time.sleep(0.01)    # Not very efficient
+        raise ProcError(self, "gave up waiting for '%s' after %ss" % (regexp, timeout))
+
+def _tc_missing(attr):
+    return not hasattr(unittest.TestCase, attr)
+
+class ProcTestCase(unittest.TestCase):
+    """TestCase that manages started processes
+
+    Also roughly provides setUpClass() and tearDownClass() and other features
+    missing in python 2.6. If subclasses override setUp() or tearDown() they
+    *must* call the superclass.
+    """
+
+    def setUp(self):
+        super(ProcTestCase, self).setUp()
+        self.procs = []
+
+    def tearDown(self):
+        for p in self.procs:
+            p.kill()
+        super(ProcTestCase, self).tearDown()
+
+    def proc(self, *args, **kwargs):
+        """Return a Proc() that will be automatically killed on teardown"""
+        p = Proc(*args, **kwargs)
+        self.procs.append(p)
+        return p
+
+    if _tc_missing('setUpClass') and _tc_missing('tearDownClass'):
+
+        @classmethod
+        def setUpClass(cls):
+            pass
+
+        @classmethod
+        def tearDownClass(cls):
+            pass
+
+        def setUp(self):
+            super(ProcTestCase, self).setUp()
+            cls = type(self)
+            if not hasattr(cls, '_setup_class_count'): # First time
+                def is_test(m):
+                    return inspect.ismethod(m) and m.__name__.startswith('test_')
+                cls._setup_class_count = len(inspect.getmembers(cls, predicate=is_test))
+                cls.setUpClass()
+
+        def tearDown(self):
+            self.assertTrue(self._setup_class_count > 0)
+            self._setup_class_count -=  1
+            if self._setup_class_count == 0:
+                type(self).tearDownClass()
+            super(ProcTestCase, self).tearDown()
+
+    if _tc_missing('assertIn'):
+        def assertIn(self, a, b):
+            self.assertTrue(a in b, "%r not in %r" % (a, b))
+
+    if _tc_missing('assertMultiLineEqual'):
+        def assertMultiLineEqual(self, a, b):
+            self.assertEqual(a, b)
+
+from unittest import main
+if __name__ == "__main__":
+    main()


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


Mime
View raw message