[rtems-tools commit] rtemstoolkit: Add unit testing for the python modules

Chris Johns chrisj at rtems.org
Tue Nov 27 02:55:44 UTC 2018


Module:    rtems-tools
Branch:    master
Commit:    7e5cdeaabeaa95b8533af626b99a43c93e5ecf6f
Changeset: http://git.rtems.org/rtems-tools/commit/?id=7e5cdeaabeaa95b8533af626b99a43c93e5ecf6f

Author:    Chris Johns <chrisj at rtems.org>
Date:      Fri Nov 23 15:02:52 2018 +1100

rtemstoolkit: Add unit testing for the python modules

- Add support to run the unit tests for the rtemstoolkit python
  modules from waf. Enter './waf test' for the tests to be run on
  python2 and python3.
- Update the importing of rtemstoolkit modules to the standard
  method which works on python2 and python3.
- Update the README.

---

 README                   | 27 ++++++++++++++++++------
 rtemstoolkit/__init__.py | 26 ++++++++---------------
 rtemstoolkit/check.py    | 32 +++++++++-------------------
 rtemstoolkit/config.py   | 24 ++++++---------------
 rtemstoolkit/darwin.py   |  9 +-------
 rtemstoolkit/freebsd.py  | 12 ++---------
 rtemstoolkit/git.py      | 20 +++++-------------
 rtemstoolkit/host.py     | 10 +--------
 rtemstoolkit/linux.py    | 12 ++---------
 rtemstoolkit/log.py      |  9 +-------
 rtemstoolkit/macros.py   | 15 +++-----------
 rtemstoolkit/mailer.py   | 28 ++++++++++++-------------
 rtemstoolkit/netbsd.py   |  8 ++-----
 rtemstoolkit/options.py  | 30 +++++++--------------------
 rtemstoolkit/path.py     | 12 ++---------
 rtemstoolkit/rtems.py    |  5 ++++-
 rtemstoolkit/solaris.py  | 11 +++-------
 rtemstoolkit/textbox.py  | 15 ++++----------
 rtemstoolkit/version.py  | 17 ++++-----------
 rtemstoolkit/windows.py  | 12 ++---------
 wscript                  | 54 +++++++++++++++++++++++++++++++++++++++++++++---
 21 files changed, 155 insertions(+), 233 deletions(-)

diff --git a/README b/README
index 763960a..115befd 100644
--- a/README
+++ b/README
@@ -28,17 +28,32 @@ Building
 
 To build and install:
 
- $ ./waf configure --prefix=$HOME/development/rtems/4.11
+ $ ./waf configure --prefix=$HOME/development/rtems/5
  $ ./waf build install
 
+Testing
+-------
+
+To the run the tests build then enter:
+
+ $ ./waf test
+
+Python
+------
+
+The RTEMS Tools supports python3 and python2. The commands look for python3,
+then python2 and finally python and use the first it finds.
+
+You can forced a specific version for testing by setting the environment
+variable 'RTEMS_PYTHON_OVERRIDE' to the python you want to use. For example:
+
+ $ export RTEMS_PYTHON_OVERRIDE=python2
+
+will use python2.
+
 Waf
 ---
 
 The Waf project can be found here:
 
  http://code.google.com/p/waf/
-
-Simple instructions on How to set up Waf is here:
-
- http://www.rtems.org/ftp/pub/rtems/people/chrisj/rtl/rtems-linker/waf.html
-
diff --git a/rtemstoolkit/__init__.py b/rtemstoolkit/__init__.py
index 6878782..207698a 100644
--- a/rtemstoolkit/__init__.py
+++ b/rtemstoolkit/__init__.py
@@ -46,20 +46,12 @@ all = ['check',
        'textbox',
        'version']
 
-from . import check
-from . import config
-from . import configuration
-from . import error
-from . import execute
-from . import git
-from . import host
-from . import log
-from . import macros
-from . import mailer
-from . import options
-from . import path
-from . import reraise
-from . import rtems
-from . import stacktraces
-from . import textbox
-from . import version
+args = {
+    'config': ['--file', 'tester/rtems/version.cfg',
+               '--jobs', 'half',
+               '--no-clean'],
+    'mailer': ['--smtp-host', '1.2.3.4',
+               '--mail-to',   'foo at bar.none',
+               '--mail-from', 'me at here.there']
+
+}
diff --git a/rtemstoolkit/check.py b/rtemstoolkit/check.py
index c6549bf..8d4a35c 100644
--- a/rtemstoolkit/check.py
+++ b/rtemstoolkit/check.py
@@ -36,24 +36,12 @@ from __future__ import print_function
 
 import os
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-    from . import execute
-    from . import log
-    from . import options
-    from . import path
-    from . import version
-except (ValueError, SystemError):
-    import error
-    import execute
-    import log
-    import options
-    import path
-    import version
+from rtemstoolkit import error
+from rtemstoolkit import execute
+from rtemstoolkit import log
+from rtemstoolkit import options
+from rtemstoolkit import path
+from rtemstoolkit import version
 
 def _check_none(_opts, macro, value, constraint):
     return True
@@ -163,12 +151,12 @@ def check_dir(label, path):
     return _check_dir(None, label, path, 'required', True)
 
 
-def run():
+def run(args):
     import sys
     try:
-        _opts = options.command_line(argv = sys.argv)
+        _opts = options.command_line(argv = args)
         options.load(_opts)
-        log.notice('RTEMS Source Builder - Check, v%s' % (version.string()))
+        log.notice('RTEMS Toolkit - Check, v%s' % (version.string()))
         if host_setup(_opts):
             print('Environment is ok')
         else:
@@ -188,4 +176,4 @@ def run():
 
 
 if __name__ == '__main__':
-    run()
+    run(['tester'])
diff --git a/rtemstoolkit/config.py b/rtemstoolkit/config.py
index a16261b..be100f2 100644
--- a/rtemstoolkit/config.py
+++ b/rtemstoolkit/config.py
@@ -44,24 +44,12 @@ import os
 import re
 import sys
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-    from . import execute
-    from . import host
-    from . import log
-    from . import options
-    from . import path
-except (ValueError, SystemError):
-    import error
-    import execute
-    import host
-    import log
-    import options
-    import path
+from rtemstoolkit import error
+from rtemstoolkit import execute
+from rtemstoolkit import host
+from rtemstoolkit import log
+from rtemstoolkit import options
+from rtemstoolkit import path
 
 def _check_bool(value):
     if value.isdigit():
diff --git a/rtemstoolkit/darwin.py b/rtemstoolkit/darwin.py
index 0400174..f7ce0da 100644
--- a/rtemstoolkit/darwin.py
+++ b/rtemstoolkit/darwin.py
@@ -35,14 +35,7 @@
 
 import os
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import execute
-except (ValueError, SystemError):
-    import execute
+from rtemstoolkit import execute
 
 def cpus():
     sysctl = '/usr/sbin/sysctl '
diff --git a/rtemstoolkit/freebsd.py b/rtemstoolkit/freebsd.py
index 2842394..ed16140 100644
--- a/rtemstoolkit/freebsd.py
+++ b/rtemstoolkit/freebsd.py
@@ -35,16 +35,8 @@
 
 import os
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import check
-    from . import execute
-except (ValueError, SystemError):
-    import check
-    import execute
+from rtemstoolkit import check
+from rtemstoolkit import execute
 
 def cpus():
     sysctl = '/sbin/sysctl '
diff --git a/rtemstoolkit/git.py b/rtemstoolkit/git.py
index 5f3af58..e1dd029 100644
--- a/rtemstoolkit/git.py
+++ b/rtemstoolkit/git.py
@@ -31,20 +31,10 @@
 
 import os
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-    from . import execute
-    from . import log
-    from . import path
-except (ValueError, SystemError):
-    import error
-    import execute
-    import log
-    import path
+from rtemstoolkit import error
+from rtemstoolkit import execute
+from rtemstoolkit import log
+from rtemstoolkit import path
 
 class repo:
     """An object to manage a git repo."""
@@ -220,7 +210,7 @@ class repo:
 
 if __name__ == '__main__':
     import sys
-    import options
+    from rtemstoolkit import options
     long_opts = {
        # key              macro        handler   param  defs   init
     }
diff --git a/rtemstoolkit/host.py b/rtemstoolkit/host.py
index ea23b24..64032f8 100644
--- a/rtemstoolkit/host.py
+++ b/rtemstoolkit/host.py
@@ -36,14 +36,7 @@ from __future__ import print_function
 
 import os
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-except (ValueError, SystemError):
-    import error
+from rtemstoolkit import error
 
 is_windows = False
 platform = None
@@ -113,7 +106,6 @@ def label(mode = 'all'):
 
 if __name__ == '__main__':
     import pprint
-    pprint.pprint(platform())
     _load()
     print('Name      : %s' % (name))
     if is_windows:
diff --git a/rtemstoolkit/linux.py b/rtemstoolkit/linux.py
index 1d7f577..7e45409 100644
--- a/rtemstoolkit/linux.py
+++ b/rtemstoolkit/linux.py
@@ -36,16 +36,8 @@
 import os
 import platform
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import execute
-    from . import path
-except (ValueError, SystemError):
-    import execute
-    import path
+from rtemstoolkit import execute
+from rtemstoolkit import path
 
 def cpus():
     processors = '/bin/grep processor /proc/cpuinfo'
diff --git a/rtemstoolkit/log.py b/rtemstoolkit/log.py
index 76a2767..a06c8c1 100755
--- a/rtemstoolkit/log.py
+++ b/rtemstoolkit/log.py
@@ -38,14 +38,7 @@ import os
 import sys
 import threading
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-except (ValueError, SystemError):
-    import error
+from rtemstoolkit import error
 
 #
 # A global log.
diff --git a/rtemstoolkit/macros.py b/rtemstoolkit/macros.py
index ed8cd96..e3776bd 100644
--- a/rtemstoolkit/macros.py
+++ b/rtemstoolkit/macros.py
@@ -40,18 +40,9 @@ import re
 import os
 import string
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-    from . import log
-    from . import path
-except (ValueError, SystemError):
-    import error
-    import log
-    import path
+from rtemstoolkit import error
+from rtemstoolkit import log
+from rtemstoolkit import path
 
 #
 # Macro tables
diff --git a/rtemstoolkit/mailer.py b/rtemstoolkit/mailer.py
index b5a0a1e..ee4d3a4 100644
--- a/rtemstoolkit/mailer.py
+++ b/rtemstoolkit/mailer.py
@@ -38,18 +38,9 @@ import os
 import smtplib
 import socket
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-    from . import options
-    from . import path
-except (ValueError, SystemError):
-    import error
-    import options
-    import path
+from rtemstoolkit import error
+from rtemstoolkit import options
+from rtemstoolkit import path
 
 _options = {
     '--mail'     : 'Send email report or results.',
@@ -161,10 +152,19 @@ class mail:
 
 if __name__ == '__main__':
     import sys
+    from rtemstoolkit import macros
     optargs = {}
+    rtdir = 'rtemstoolkit'
+    defaults = '%s/defaults.mc' % (rtdir)
     append_options(optargs)
-    opts = options.load(sys.argv, optargs = optargs, defaults = 'defaults.mc')
+    opts = options.command_line(base_path = '.',
+                                argv = sys.argv,
+                                optargs = optargs,
+                                defaults = macros.macros(name = defaults, rtdir = rtdir),
+                                command_path = '.')
+    options.load(opts)
     m = mail(opts)
     print('From: %s' % (m.from_address()))
     print('SMTP Host: %s' % (m.smtp_host()))
-    m.send(m.from_address(), 'Test mailer.py', 'This is a test')
+    if '--mail' in sys.argv:
+        m.send(m.from_address(), 'Test mailer.py', 'This is a test')
diff --git a/rtemstoolkit/netbsd.py b/rtemstoolkit/netbsd.py
index 112fba1..1d9a11f 100644
--- a/rtemstoolkit/netbsd.py
+++ b/rtemstoolkit/netbsd.py
@@ -26,12 +26,8 @@
 
 import os
 
-try:
-    from . import check
-    from . import execute
-except (ValueError, SystemError):
-    import check
-    import execute
+from rtemstoolkit import check
+from rtemstoolkit import execute
 
 def cpus():
     sysctl = '/sbin/sysctl '
diff --git a/rtemstoolkit/options.py b/rtemstoolkit/options.py
index 77d9593..dcb8980 100644
--- a/rtemstoolkit/options.py
+++ b/rtemstoolkit/options.py
@@ -42,28 +42,14 @@ import os
 import string
 import sys
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-    from . import execute
-    from . import git
-    from . import host
-    from . import log
-    from . import macros
-    from . import path
-    from . import version
-except (ValueError, SystemError):
-    import error
-    import execute
-    import git
-    import host
-    import log
-    import macros
-    import path
-    import version
+from rtemstoolkit import error
+from rtemstoolkit import execute
+from rtemstoolkit import git
+from rtemstoolkit import host
+from rtemstoolkit import log
+from rtemstoolkit import macros
+from rtemstoolkit import path
+from rtemstoolkit import version
 
 basepath = 'tb'
 
diff --git a/rtemstoolkit/path.py b/rtemstoolkit/path.py
index 83fb361..2b569ae 100644
--- a/rtemstoolkit/path.py
+++ b/rtemstoolkit/path.py
@@ -41,16 +41,8 @@ import os
 import shutil
 import string
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-    from . import log
-except (ValueError, SystemError):
-    import error
-    import log
+from rtemstoolkit import error
+from rtemstoolkit import log
 
 windows = os.name == 'nt'
 
diff --git a/rtemstoolkit/rtems.py b/rtemstoolkit/rtems.py
index 157cb5b..fc46946 100755
--- a/rtemstoolkit/rtems.py
+++ b/rtemstoolkit/rtems.py
@@ -71,7 +71,10 @@ def configuration_path(prog = None):
      2. Ok to directly call os.path.
     '''
     if prog is None:
-        exec_name = sys.argv[1]
+        if len(sys.argv) == 1:
+            exec_name = sys.argv[0]
+        else:
+            exec_name = sys.argv[1]
     else:
         exec_name = prog
     exec_name = os.path.abspath(exec_name)
diff --git a/rtemstoolkit/solaris.py b/rtemstoolkit/solaris.py
index dc3e490..79ddd75 100644
--- a/rtemstoolkit/solaris.py
+++ b/rtemstoolkit/solaris.py
@@ -24,14 +24,9 @@
 
 import os
 
-try:
-    from . import check
-    from . import error
-    from . import execute
-except (ValueError, SystemError):
-    import check
-    import error
-    import execute
+from rtemstoolkit import check
+from rtemstoolkit import error
+from rtemstoolkit import execute
 
 def cpus():
     psrinfo = '/sbin/psrinfo|wc -l'
diff --git a/rtemstoolkit/textbox.py b/rtemstoolkit/textbox.py
index 8341bdd..441e333 100644
--- a/rtemstoolkit/textbox.py
+++ b/rtemstoolkit/textbox.py
@@ -39,19 +39,12 @@ from __future__ import print_function
 import copy
 import os
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-except (ValueError, SystemError):
-    import error
+from rtemstoolkit import error
 
 def line(cols, line = '-', marker = '|', indent = 0, linesep = os.linesep):
     s = ' ' * indent + marker
     for c in cols:
-        s += line[0] * (c - 1) + marker
+        s += line[0] * int((c - 1)) + marker
     return s + linesep
 
 def row(cols, data, indent = 0, marker = '|', linesep = os.linesep):
@@ -64,13 +57,13 @@ def row(cols, data, indent = 0, marker = '|', linesep = os.linesep):
             m = marker
         else:
             m = '|'
-        s += '%-*s%s' % (cols[c] - 1, str(data[c]), m)
+        s += '%-*s%s' % (int(cols[c] - 1), str(data[c]), m)
     return s + linesep
 
 def even_columns(cols, width = 80):
     per_col = width / cols
     columns = [per_col for c in range(0, cols)]
-    for remainder in range(0, width - (per_col * cols)):
+    for remainder in range(0, int(width - (per_col * cols))):
         if remainder % 2 == 0:
             columns[remainder] += 1
         else:
diff --git a/rtemstoolkit/version.py b/rtemstoolkit/version.py
index 6f76c84..54b6af4 100644
--- a/rtemstoolkit/version.py
+++ b/rtemstoolkit/version.py
@@ -88,19 +88,10 @@ try:
 except ImportError:
     import ConfigParser as configparser
 
-#
-# Support to handle importing when installed in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-    from . import git
-    from . import rtems
-except (ValueError, SystemError):
-    import error
-    import git
-    import path
-    import rtems
+from rtemstoolkit import error
+from rtemstoolkit import git
+from rtemstoolkit import path
+from rtemstoolkit import rtems
 
 #
 # Default to an internal string.
diff --git a/rtemstoolkit/windows.py b/rtemstoolkit/windows.py
index 8f51069..c40f7bd 100644
--- a/rtemstoolkit/windows.py
+++ b/rtemstoolkit/windows.py
@@ -34,16 +34,8 @@
 
 import os
 
-#
-# Support to handle use in a package and as a unit test.
-# If there is a better way to let us know.
-#
-try:
-    from . import error
-    from . import execute
-except (ValueError, SystemError):
-    import error
-    import execute
+from rtemstoolkit import error
+from rtemstoolkit import execute
 
 def cpus():
     if os.environ.has_key('NUMBER_OF_PROCESSORS'):
diff --git a/wscript b/wscript
index adbe766..c2e55c7 100644
--- a/wscript
+++ b/wscript
@@ -95,6 +95,11 @@ def configure(ctx):
     ctx.load('python')
     ctx.check_python_version((2,6,6))
     #
+    # Find which versions of python are installed for testing.
+    #
+    ctx.find_program('python2', mandatory = False)
+    ctx.find_program('python3', mandatory = False)
+    #
     # Installing the PYO,PYC seems broken on 1.8.19. The path is wrong.
     #
     ctx.env.PYO = 0
@@ -105,6 +110,8 @@ def build(ctx):
     if os.path.exists('VERSION'):
         ctx.install_files('${PREFIX}/share/rtems/rtemstoolkit', ['VERSION'])
     recurse(ctx)
+    if ctx.cmd == 'test':
+        rtemstoolkit_tests(ctx)
 
 def install(ctx):
     recurse(ctx)
@@ -127,9 +134,50 @@ def check_options(ctx, host):
         ctx.fatal('unknown host: %s' % (host));
 
 #
-# The doxy command.
+# Custom commands
 #
-from waflib import Build
-class doxy(Build.BuildContext):
+import waflib
+
+class test(waflib.Build.BuildContext):
+    fun = 'build'
+    cmd = 'test'
+
+class doxy(waflib.Build.BuildContext):
     fun = 'build'
     cmd = 'doxy'
+
+#
+# RTEMS Toolkit Tests.
+#
+# Run the tests from the top directory so they are run as python modules.
+#
+def rtemstoolkit_tests(ctx):
+    log = ctx.path.find_or_declare('tests.log')
+    ctx.logger = waflib.Logs.make_logger(log.abspath(), 'build')
+    failures = False
+    for py in ['2', '3']:
+        PY = 'PYTHON%s' % (py)
+        if PY in ctx.env:
+            from rtemstoolkit import all as toolkit_tests
+            from rtemstoolkit import args as toolkit_test_args
+            for tt in toolkit_tests:
+                test = 'rtemstoolkit.%s' % (tt)
+                ctx.start_msg('Test python%s %s' % (py, test))
+                cmd = '%s -m %s' % (ctx.env[PY][0], test)
+                if tt in toolkit_test_args:
+                    cmd += ' ' + ' '.join(toolkit_test_args[tt])
+                ctx.to_log('test command: ' + cmd)
+                try:
+                    (out, err) = ctx.cmd_and_log(cmd,
+                                                 output = waflib.Context.BOTH,
+                                                 quiet = waflib.Context.BOTH)
+                    ctx.to_log(out)
+                    ctx.to_log(err)
+                    ctx.end_msg('pass')
+                except waflib.Errors.WafError as e:
+                    failures = True
+                    ctx.to_log(e.stdout)
+                    ctx.to_log(e.stderr)
+                    ctx.end_msg('fail', color = 'RED')
+    if failures:
+        ctx.fatal('Test failures')



More information about the vc mailing list