diff options
author | Chris Johns <chrisj@rtems.org> | 2014-02-15 06:30:06 +1100 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2014-02-15 06:30:06 +1100 |
commit | 50fdf12244e784bd52732be1e68d966bc9629b24 (patch) | |
tree | 93b6656d397f3ef358b50aeaef6dc4d10a653f8c /tester | |
parent | 8f75c4a380cb0a4330f65966784ccdfeff756e70 (diff) |
rt: Add the rtems-tester.
Diffstat (limited to 'tester')
30 files changed, 4199 insertions, 0 deletions
diff --git a/tester/.gitignore b/tester/.gitignore new file mode 100644 index 0000000..7e4a24c --- /dev/null +++ b/tester/.gitignore @@ -0,0 +1,4 @@ +*~ +*.pyc +*.log +log_* diff --git a/tester/config/base.cfg b/tester/config/base.cfg new file mode 100644 index 0000000..bb058d2 --- /dev/null +++ b/tester/config/base.cfg @@ -0,0 +1,35 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# Base settings for RTEMS testing support. +# + +%define _target %{%{bsp_arch}-rtems%{version} diff --git a/tester/config/checks.cfg b/tester/config/checks.cfg new file mode 100644 index 0000000..b21d912 --- /dev/null +++ b/tester/config/checks.cfg @@ -0,0 +1,37 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# Commdon checks for the RTEMS Tests. +# + +%if %{_target} == %{nil} + %error No 'target' defined +%endif diff --git a/tester/rt/__init__.py b/tester/rt/__init__.py new file mode 100644 index 0000000..c7eac97 --- /dev/null +++ b/tester/rt/__init__.py @@ -0,0 +1,30 @@ +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +all = ['test'] diff --git a/tester/rt/config.py b/tester/rt/config.py new file mode 100644 index 0000000..d426026 --- /dev/null +++ b/tester/rt/config.py @@ -0,0 +1,205 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# RTEMS Testing Config +# + +import datetime +import os +import threading + +from rtemstoolkit import config +from rtemstoolkit import error +from rtemstoolkit import execute +from rtemstoolkit import log +from rtemstoolkit import path + +import console +import gdb + +timeout = 15 + +class file(config.file): + """RTEMS Testing configuration.""" + + _directives = ['%execute', + '%gdb', + '%console'] + + def __init__(self, report, name, opts, _directives = _directives): + super(file, self).__init__(name, opts, directives = _directives) + self.lock = threading.Lock() + self.realtime_trace = self.debug_trace('output') + self.process = None + self.console = None + self.output = None + self.report = report + self.load(name) + + def __del__(self): + if self.console: + del self.console + super(file, self).__del__() + + def _lock(self): + self.lock.acquire() + + def _unlock(self): + self.lock.release() + + def _timeout(self): + self.capture('*** TIMEOUT TIMEOUT') + + def _dir_console(self, data): + if self.console is not None: + raise error.general(self._name_line_msg('console already configured')) + if len(data) == 0: + raise error.general(self._name_line_msg('no console configuration provided')) + console_trace = trace = self.debug_trace('console') + if data[0] == 'stdio': + self.console = console.stdio(trace = console_trace) + elif data[0] == 'tty': + if len(data) < 2 or len(data) >3: + raise error.general(self._name_line_msg('no tty configuration provided')) + if len(data) == 3: + settings = data[2] + else: + settings = None + self.console = console.tty(data[1], + output = self.capture, + setup = settings, + trace = console_trace) + else: + raise error.general(self._name_line_msg('invalid console type')) + + def _dir_execute(self, data, total, index, exe, bsp_arch, bsp): + self.process = execute.execute(output = self.capture) + if not self.in_error: + if self.console: + self.console.open() + self.capture_console('run: %s' % (' '.join(data))) + ec, proc = self.process.open(data, + timeout = (int(self.expand('%{timeout}')), + self._timeout)) + if ec > 0: + self._lock() + self._error('execute failed: %s: %s' % (' '.join(data), os.strerror(ec))) + self._unlock() + if self.console: + self.console.close() + + def _dir_gdb(self, data, total, index, exe, bsp_arch, bsp): + if len(data) < 3 or len(data) > 4: + raise error.general('invalid %gdb arguments') + self.process = gdb.gdb(bsp_arch, bsp, + trace = self.debug_trace('gdb'), + mi_trace = self.debug_trace('gdb-mi')) + script = self.expand('%%{%s}' % data[2]) + if script: + script = [l.strip() for l in script.splitlines()] + if not self.in_error: + if self.console: + self.console.open() + self.process.open(data[0], data[1], + script = script, + output = self.capture, + gdb_console = self.capture_console, + timeout = int(self.expand('%{timeout}'))) + if self.console: + self.console.close() + + def _directive_filter(self, results, directive, info, data): + if results[0] == 'directive': + _directive = results[1] + _data = results[2] + ds = [] + if len(_data): + ds = [_data[0]] + if len(_data) > 1: + ds += _data[1].split() + ds = self.expand(ds) + + if _directive == '%console': + self._dir_console(ds) + else: + self._lock() + try: + total = int(self.expand('%{test_total}')) + index = int(self.expand('%{test_index}')) + exe = self.expand('%{test_executable}') + bsp_arch = self.expand('%{bsp_arch}') + bsp = self.expand('%{bsp}') + self.report.start(index, total, exe, exe, bsp_arch, bsp) + self.output = [] + finally: + self._unlock() + if _directive == '%execute': + self._dir_execute(ds, total, index, exe, bsp_arch, bsp) + elif _directive == '%gdb': + self._dir_gdb(ds, total, index, exe, bsp_arch, bsp) + else: + raise error.general(self._name_line_msg('invalid directive')) + self._lock() + try: + self.report.end(exe, self.output) + self.process = None + self.output = None + finally: + self._unlock() + return None, None, None + + def _realtime_trace(self, text): + if self.realtime_trace: + for l in text: + print ' '.join(l) + + def capture(self, text): + text = [(']', l) for l in text.replace(chr(13), '').splitlines()] + self._lock() + if self.output is not None: + self._realtime_trace(text) + self.output += text + self._unlock() + + def capture_console(self, text): + text = [('>', l) for l in text.replace(chr(13), '').splitlines()] + self._lock() + if self.output is not None: + self._realtime_trace(text) + self.output += text + self._unlock() + + def debug_trace(self, flag): + dt = self.macros['debug_trace'] + if dt: + if flag in dt.split(','): + return True + return False diff --git a/tester/rt/console.py b/tester/rt/console.py new file mode 100644 index 0000000..74ec3bf --- /dev/null +++ b/tester/rt/console.py @@ -0,0 +1,143 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# RTEMS Testing Consoles +# + +import errno +import fcntl +import os +import threading +import time + +import stty + +def save(): + return stty.save() + +def restore(attributes): + stty.restore(attributes) + +class console(object): + '''RTEMS Testing console base.''' + + def __init__(self, name, trace): + self.name = name + self.trace = trace + + def __del__(self): + pass + + def _tracing(self): + return self.trace + + def open(self): + pass + + def close(self): + pass + +class stdio(console): + '''STDIO console.''' + + def __init__(self, trace = False): + super(stdio, self).__init__('stdio', trace) + +class tty(console): + '''TTY console connects to serial ports.''' + + raw = 'B115200,~BRKINT,IGNBRK,IGNCR,~ICANON,~ISIG,~IEXTEN,~ECHO,CLOCAL,~CRTSCTS' + + def __init__(self, dev, output, setup = None, trace = False): + self.tty = None + self.read_thread = None + self.dev = dev + self.output = output + if setup is None: + self.setup = raw + else: + self.setup = setup + super(tty, self).__init__(dev, trace) + + def __del__(self): + super(tty, self).__del__() + if self._tracing(): + print ':: tty close', self.dev + fcntl.fcntl(me.tty.fd, fcntl.F_SETFL, + fcntl.fcntl(me.tty.fd, fcntl.F_GETFL) & ~os.O_NONBLOCK) + self.close() + + def open(self): + def _readthread(me, x): + if self._tracing(): + print ':: tty runner started', self.dev + fcntl.fcntl(me.tty.fd, fcntl.F_SETFL, + fcntl.fcntl(me.tty.fd, fcntl.F_GETFL) | os.O_NONBLOCK) + line = '' + while me.running: + time.sleep(0.05) + try: + data = me.tty.fd.read() + except IOError, ioe: + if ioe.errno == errno.EAGAIN: + continue + raise + except: + raise + for c in data: + if len(c) == 0: + continue + if c != chr(0): + line += c + if c == '\n': + me.output(line) + line = '' + if self._tracing(): + print ':: tty runner finished', self.dev + if self._tracing(): + print ':: tty open', self.dev + self.tty = stty.tty(self.dev) + self.tty.set(self.setup) + self.tty.on() + self.read_thread = threading.Thread(target = _readthread, + name = 'tty[%s]' % (self.dev), + args = (self, 0)) + self.read_thread.daemon = True + self.running = True + self.read_thread.start() + + def close(self): + if self.tty: + time.sleep(1) + if self.read_thread: + self.running = False + self.read_thread.join(1) + self.tty = None diff --git a/tester/rt/gdb.py b/tester/rt/gdb.py new file mode 100644 index 0000000..4449222 --- /dev/null +++ b/tester/rt/gdb.py @@ -0,0 +1,321 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# RTEMS Testing GDB Interface +# + +import os +import Queue +import sys +import termios +import threading + +from rtemstoolkit import error +from rtemstoolkit import execute +from rtemstoolkit import options +from rtemstoolkit import path + +import console +import pygdb + +# +# The MI parser needs a global lock. It has global objects. +# +mi_lock = threading.Lock() + +class gdb(object): + '''RTEMS Testing GDB base.''' + + def __init__(self, bsp_arch, bsp, trace = False, mi_trace = False): + self.trace = trace + self.mi_trace = mi_trace + self.lock_trace = False + self.lock = threading.RLock() + self.script = None + self.script_line = 0 + self.bsp = bsp + self.bsp_arch = bsp_arch + self.output = None + self.gdb_console = None + self.input = Queue.Queue() + self.commands = Queue.Queue() + self.process = None + self.state = {} + self.running = False + self.breakpoints = {} + self.output = None + self.output_buffer = '' + self.lc = 0 + + def _lock(self, msg): + if self.lock_trace: + print '|[ LOCK:%s ]|' % (msg) + self.lock.acquire() + + def _unlock(self, msg): + if self.lock_trace: + print '|] UNLOCK:%s [|' % (msg) + self.lock.release() + + def _mi_lock(self): + mi_lock.acquire() + + def _mi_unlock(self): + mi_lock.release() + + def _put(self, text): + if self.trace: + print ')))', text + self.commands.put(text) + + def _input_commands(self): + if self.commands.empty(): + return False + try: + if self.trace: + print '... input empty ', self.input.empty() + if self.input.empty(): + line = self.commands.get(block = False) + if self.trace: + print '+++', line + self.input.put(line) + except: + pass + return True + + def _reader(self, line): + self._lock('_reader') + if self.trace: + print '<<<', line + try: + self.lc += 1 + if line.startswith('(gdb)'): + if self.trace: + print '^^^ (gdb)' + if not self._input_commands(): + self.gdb_expect() + self._input_commands() + else: + self.gdb_parse(line) + finally: + self._unlock('_reader') + + def _writer(self): + try: + try: + self._lock('_open') + try: + if self.process is None: + return None + finally: + self._unlock('_open') + line = self.input.get(timeout = 0.5) + if self.trace: + print '>>> input: queue=%d' % (self.input.qsize()), line + except Queue.Empty: + return True + if line is None: + return None + return line + os.linesep + except: + if self.trace: + print 'writer exception' + pass + if self.trace: + print 'writer closing' + return False + + def _timeout(self): + self._lock('_timeout') + try: + if self.output: + self.output('*** TIMEOUT TIMEOUT') + self._gdb_quit(backtrace = True) + finally: + self._unlock('_timeout') + + def _cleanup(self, proc): + self._lock('_cleanup') + try: + self._put(None) + finally: + self._unlock('_cleanup') + + def _gdb_quit(self, backtrace = False): + self._lock('_gdb_quit') + try: + self._put('-exec-interrupt') + if backtrace: + self._put('bt') + self._put('quit') + self._put('None') + if self.script: + self.script_line = len(self.script) + finally: + self._unlock('_gdb_quit') + + def open(self, command, executable, + output, gdb_console, script = None, tty = None, + timeout = 300): + self._lock('_open') + try: + cmds = execute.arg_list(command) + ['-i=mi', + '--nx', + '--quiet'] + if tty: + cmds += ['--tty=%s' % tty] + if executable: + cmds += [executable] + self.output = output + self.gdb_console = gdb_console + self.script = script + self.running = False + self.process = execute.execute(output = self._reader, + input = self._writer, + cleanup = self._cleanup) + finally: + self._unlock('_open') + try: + self.gdb_console('gdb: %s' % (' '.join(cmds))) + ec, proc = self.process.open(cmds, timeout = (timeout, self._timeout)) + if self.trace: + print 'gdb done', ec + if ec > 0: + raise error.general('gdb exec: %s' % (os.strerror(ec))) + except: + raise + self._lock('_open') + try: + self.process = None + finally: + self._unlock('_open') + + def gdb_expect(self): + if self.trace: + print '}}} gdb-expect' + if self.process and not self.running and self.script is not None: + if self.script_line == len(self.script): + self._put(None) + else: + if self.script_line == 0: + self._put('-gdb-set confirm no') + self._put('-data-list-register-names') + line = self.script[self.script_line] + self.script_line += 1 + self._put(line) + else: + self._put(line) + + def gdb_parse(self, lines): + try: + self._mi_lock() + try: + if self.mi_trace: + print 'mi-data:', lines + rec = pygdb.mi_parser.process(lines) + finally: + self._mi_unlock() + if self.mi_trace: + print 'mi-rec:', rec + if rec.record_type == 'result': + if rec.type == 'result': + if rec.class_ == 'error': + self._gdb_quit() + elif 'register_names' in dir(rec.result): + self.register_names = rec.result.register_names + elif 'register_values' in dir(rec.result): + self.register_values = rec.result.register_values + elif rec.type == 'exec': + if rec.class_ == 'running': + if self.trace: + print '*** running' + self._put('') + self.running = True + elif rec.class_ == 'stopped': + if self.trace: + print '*** stopped' + self.running = False + #self._put('-data-list-register-values') + elif rec.type == 'breakpoint': + if rec.class_ == 'breakpoint-created': + self.breakpoints[rec.result.bkpt.number] = rec.result.bkpt + elif rec.class_ == 'breakpoint-modified': + self.breakpoints[rec.result.bkpt.number] = rec.result.bkpt + elif rec.class_ == 'breakpoint-deleted': + if rec.result.id in self.breakpoints: + del self.breakpoints[rec.result.id] + elif rec.record_type == 'error': + self._gdb_quit() + elif rec.record_type == 'stream': + if rec.type == 'console' or rec.type == 'log': + for line in rec.value.splitlines(): + self.gdb_console(line) + if rec.type == 'target': + self.output_buffer += rec.value + last_lf = self.output_buffer.rfind('\n') + if last_lf >= 0: + lines = self.output_buffer[:last_lf] + if self.trace: + print '/// console output' + for line in lines.splitlines(): + self.output(line) + self.output_buffer = self.output_buffer[last_lf + 1:] + except: + if self.trace: + print '/// console output' + for line in lines.splitlines(): + self.output(line) + +if __name__ == "__main__": + stdtty = console.save() + try: + def output(text): + print ']', text + def gdb_console(text): + print '>', text + script = ['target sim'] + if len(sys.argv) > 1: + executable = sys.argv[1] + script += ['load', + 'run', + 'info reg', + '-stack-list-frames', + '-stack-list-arguments --all-values'] + else: + executable = None + script += ['quit'] + g = gdb('sparc', 'sis', mi_trace = True) + g.open('sparc-rtems4.11-gdb', executable, output, gdb_console, script) + except: + console.restore(stdtty) + raise + finally: + console.restore(stdtty) diff --git a/tester/rt/options.py b/tester/rt/options.py new file mode 100644 index 0000000..f637017 --- /dev/null +++ b/tester/rt/options.py @@ -0,0 +1,118 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# Determine the defaults and load the specific file. +# + +import glob +import pprint +import re +import os +import string + +from rtemstoolkit import error +from rtemstoolkit import execute +from rtemstoolkit import git +from rtemstoolkit import log +from rtemstoolkit import macros +from rtemstoolkit import options +from rtemstoolkit import path + +import version + +class command_line(options.command_line): + """Process the command line in a common way for all Tool Builder commands.""" + + def __init__(self, argv = None, optargs = None, defaults = None, command_path = None): + if argv is None: + return + long_opts = { + # key macro handler param defs init + '--target' : ('_target', "triplet", True, None, False), + '--timeout' : ('timeout', "int", True, None, False), + } + long_opts_help = { + '--target': 'Set the target triplet', + '--timeout': 'Set the test timeout in seconds (default 180 seconds)' + } + super(command_line, self).__init__('rt', argv, optargs, defaults, + long_opts, long_opts_help, command_path); + + def __copy__(self): + return super(command_line, self).__copy__() + +def load(args, optargs = None, + command_path = None, + defaults = '%{_rtdir}/rtems/testing/defaults.mc'): + # + # The path to this command if not supplied by the upper layers. + # + if command_path is None: + command_path = path.dirname(args[0]) + if len(command_path) == 0: + command_path = '.' + # + # The command line contains the base defaults object all build objects copy + # and modify by loading a configuration. + # + opts = command_line(args, + optargs, + macros.macros(name = defaults, + rtdir = command_path), + command_path) + options.load(opts) + return opts + +def run(args): + try: + _opts = load(args = args, defaults = 'rtems/testing/defaults.mc') + log.notice('RTEMS Test - Defaults, v%s' % (version.str())) + _opts.log_info() + log.notice('Options:') + log.notice(str(_opts)) + log.notice('Defaults:') + log.notice(str(_opts.defaults)) + except error.general, gerr: + print gerr + sys.exit(1) + except error.internal, ierr: + print ierr + sys.exit(1) + except error.exit, eerr: + pass + except KeyboardInterrupt: + log.notice('abort: user terminated') + sys.exit(1) + sys.exit(0) + +if __name__ == '__main__': + import sys + run(sys.argv) diff --git a/tester/rt/pygdb/__init__.py b/tester/rt/pygdb/__init__.py new file mode 100644 index 0000000..b52f6f9 --- /dev/null +++ b/tester/rt/pygdb/__init__.py @@ -0,0 +1,21 @@ +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +all = ['mi_parser'] +from mi_parser import scan +from mi_parser import process diff --git a/tester/rt/pygdb/mi_parser.py b/tester/rt/pygdb/mi_parser.py new file mode 100755 index 0000000..65ea5e0 --- /dev/null +++ b/tester/rt/pygdb/mi_parser.py @@ -0,0 +1,423 @@ +#!/usr/bin/python + +# +# Copyright (c) 2008 Michael Eddington +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +# Authors: +# Frank Laub (frank.laub@gmail.com) +# Michael Eddington (mike@phed.org) + +# $Id$ + + +import re +import pprint +import spark + +def __private(): + class Token: + def __init__(self, type, value=None): + self.type = type + self.value = value + def __cmp__(self, o): + return cmp(self.type, o) + def __repr__(self): + return self.value or self.type + + class AST: + def __init__(self, type): + self.type = type + self._kids = [] + def __getitem__(self, i): + return self._kids[i] + def __len__(self): + return len(self._kids) + def __setslice__(self, low, high, seq): + self._kids[low:high] = seq + def __cmp__(self, o): + return cmp(self.type, o) + + class GdbMiScannerBase(spark.GenericScanner): + def tokenize(self, input): + self.rv = [] + spark.GenericScanner.tokenize(self, input) + return self.rv + + def t_nl(self, s): + r'\n|\r\n' + self.rv.append(Token('nl')) + + def t_whitespace(self, s): + r'[ \t\f\v]+' + pass + + def t_symbol(self, s): + r',|\{|\}|\[|\]|\=' + self.rv.append(Token(s, s)) + + def t_result_type(self, s): + r'\*|\+|\^' + self.rv.append(Token('result_type', s)) + + def t_stream_type(self, s): + r'\@|\&|\~' + self.rv.append(Token('stream_type', s)) + + def t_string(self, s): + r'[\w-]+' + self.rv.append(Token('string', s)) + + def t_c_string(self, s): + r'\".*?(?<![\\\\])\"' + inner = self.__unescape(s[1:len(s)-1]) + self.rv.append(Token('c_string', inner)) + + def t_default(self, s): + r'( . | \n )+' + raise Exception, "Specification error: unmatched input for '%s'" % s + + def __unescape(self, s): + s = re.sub(r'\\r', r'\r', s) + s = re.sub(r'\\n', r'\n', s) + s = re.sub(r'\\t', r'\t', s) + return re.sub(r'\\(.)', r'\1', s) + + + class GdbMiScanner(GdbMiScannerBase): + def t_token(self, s): + r'\d+' + self.rv.append(Token('token', s)) + + class GdbMiParser(spark.GenericASTBuilder): + def __init__(self): + spark.GenericASTBuilder.__init__(self, AST, 'output') + + def p_output(self, args): + ''' + output ::= record_list + record_list ::= generic_record + record_list ::= generic_record record_list + generic_record ::= result_record + generic_record ::= stream_record + result_record ::= result_header result_list nl + result_record ::= result_header nl + result_header ::= token result_type class + result_header ::= result_type class + result_header ::= token = class + result_header ::= = class + stream_record ::= stream_type c_string nl + result_list ::= , result result_list + result_list ::= , result + result_list ::= , tuple + result ::= variable = value + class ::= string + variable ::= string + value ::= const + value ::= tuple + value ::= list + value_list ::= , value + value_list ::= , value value_list + const ::= c_string + tuple ::= { } + tuple ::= { result } + tuple ::= { result result_list } + list ::= [ ] + list ::= [ value ] + list ::= [ value value_list ] + list ::= [ result ] + list ::= [ result result_list ] + list ::= { value } + list ::= { value value_list } + ''' + pass + + def terminal(self, token): + # Homogeneous AST. + rv = AST(token.type) + rv.value = token.value + return rv + + def nonterminal(self, type, args): + # Flatten AST a bit by not making nodes if there's only one child. + exclude = [ + 'record_list' + ] + if len(args) == 1 and type not in exclude: + return args[0] + return spark.GenericASTBuilder.nonterminal(self, type, args) + + def error(self, token, i=0, tokens=None): + if i > 2: + print '%s %s %s %s' % (tokens[i-3], tokens[i-2], tokens[i-1], tokens[i]) + raise Exception, "Syntax error at or near %d:'%s' token" % (i, token) + + class GdbMiInterpreter(spark.GenericASTTraversal): + def __init__(self, ast): + spark.GenericASTTraversal.__init__(self, ast) + self.postorder() + + def __translate_type(self, type): + table = { + '^': 'result', + '=': 'notify', + '+': 'status', + '*': 'exec', + '~': 'console', + '@': 'target', + '&': 'log' + } + return table[type] + + def n_result(self, node): + # result ::= variable = value + node.value = { node[0].value: node[2].value } + #print 'result: %s' % node.value + + def n_tuple(self, node): + if len(node) == 2: + # tuple ::= {} + node.value = {} + elif len(node) == 3: + # tuple ::= { result } + node.value = node[1].value + elif len(node) == 4: + # tuple ::= { result result_list } + node.value = node[1].value + for result in node[2].value: + for n, v in result.items(): + if node.value.has_key(n): + #print '**********list conversion: [%s] %s -> %s' % (n, node.value[n], v) + old = node.value[n] + if not isinstance(old, list): + node.value[n] = [ node.value[n] ] + node.value[n].append(v) + else: + node.value[n] = v + else: + raise Exception, 'Invalid tuple' + #print 'tuple: %s' % node.value + + def n_list(self, node): + if len(node) == 2: + # list ::= [] + node.value = [] + elif len(node) == 3: + # list ::= [ value ] + node.value = [ node[1].value ] + elif len(node) == 4: + # list ::= [ value value_list ] + node.value = [ node[1].value ] + node[2].value + #list ::= [ result ] + #list ::= [ result result_list ] + #list ::= { value } + #list ::= { value value_list } + #print 'list %s' % node.value + + def n_value_list(self, node): + if len(node) == 2: + #value_list ::= , value + node.value = [ node[1].value ] + elif len(node) == 3: + #value_list ::= , value value_list + node.value = [ node[1].value ] + node[2].value + + def n_result_list(self, node): + if len(node) == 2: + # result_list ::= , result + node.value = [ node[1].value ] + else: + # result_list ::= , result result_list + node.value = [ node[1].value ] + node[2].value + #print 'result_list: %s' % node.value + + def n_result_record(self, node): + node.value = node[0].value + if len(node) == 3: + # result_record ::= result_header result_list nl + node.value['results'] = node[1].value + elif len(node) == 2: + # result_record ::= result_header nl + pass + #print 'result_record: %s' % (node.value) + + def n_result_header(self, node): + if len(node) == 3: + # result_header ::= token result_type class + node.value = { + 'token': node[0].value, + 'type': self.__translate_type(node[1].value), + 'class_': node[2].value, + 'record_type': 'result' + } + elif len(node) == 2: + # result_header ::= result_type class + node.value = { + 'token': None, + 'type': self.__translate_type(node[0].value), + 'class_': node[1].value, + 'record_type': 'result' + } + + def n_stream_record(self, node): + # stream_record ::= stream_type c_string nl + node.value = { + 'type': self.__translate_type(node[0].value), + 'value': node[1].value, + 'record_type': 'stream' + } + #print 'stream_record: %s' % node.value + + def n_record_list(self, node): + if len(node) == 1: + # record_list ::= generic_record + node.value = [ node[0].value ] + elif len(node) == 2: + # record_list ::= generic_record record_list + node.value = [ node[0].value ] + node[1].value + #print 'record_list: %s' % node.value + + #def default(self, node): + #print 'default: ' + node.type + + class GdbDynamicObject: + def __init__(self, dict_): + self.graft(dict_) + + def __repr__(self): + return pprint.pformat(self.__dict__) + + def __nonzero__(self): + return len(self.__dict__) > 0 + + def __getitem__(self, i): + if i == 0 and len(self.__dict__) > 0: + return self + else: + raise IndexError + + def __getattr__(self, name): + if name.startswith('__'): + raise AttributeError + return None + + def graft(self, dict_): + for name, value in dict_.items(): + name = name.replace('-', '_') + if isinstance(value, dict): + value = GdbDynamicObject(value) + elif isinstance(value, list): + x = value + value = [] + for item in x: + if isinstance(item, dict): + item = GdbDynamicObject(item) + value.append(item) + setattr(self, name, value) + + class GdbMiRecord: + def __init__(self, record): + self.result = None + for name, value in record[0].items(): + name = name.replace('-', '_') + if name == 'results': + for result in value: + if not self.result: + self.result = GdbDynamicObject(result) + else: + # graft this result to self.results + self.result.graft(result) + else: + setattr(self, name, value) + + def __repr__(self): + return pprint.pformat(self.__dict__) + + return (GdbMiScanner(), GdbMiParser(), GdbMiInterpreter, GdbMiRecord) + +(__the_scanner, __the_parser, __the_interpreter, __the_output) = __private() + +def scan(input): + return __the_scanner.tokenize(input) + +def parse(tokens): + return __the_parser.parse(tokens) + +def process(input): + tokens = scan(input) + ast = parse(tokens) + __the_interpreter(ast) + return __the_output(ast.value) + +if __name__ == '__main__': + def main(): + def print_tokens(tokens): + print + for token in tokens: + if token.value: + print token.type + ': ' + token.value + else: + print token.type + + def run_test(test): + lines = test.splitlines() + for line in lines: + tokens = scan(line + '\n') + #print_tokens(tokens) + + ast = parse(tokens) + __the_interpreter(ast) + output = __the_output(ast.value) + print output + + x = '"No symbol table is loaded. Use the \\"file\\" command."' + m = re.match('\".*?(?<![\\\\])\"', x) + z = x[m.start():m.end()] + + test1 = '22^done,time={wallclock="0.05395",user="0.02996",system="0.02222",start="1210321030.972724",end="1210321031.026675"}\n' + test2 = '''~"[Switching to process 3832 local thread 0x3607]\\n" +=shlibs-updated +^running +''' + + test3 = '''=shlibs-added,shlib-info={num="2",name="qi",kind="-",dyld-addr="0x1000",reason="exec",requested-state="Y",state="Y",path="/Users/franklaub/bin/qi",description="/Users/franklaub/bin/qi",loaded_addr="",slide="0x0",prefix="",dsym-objpath="/Users/franklaub/bin/qi.dSYM/Contents/Resources/DWARF/qi"},time={now="1210290757.432413"} +=shlibs-added,shlib-info={num="3",name="libgcc_s.1.dylib",kind="-",dyld-addr="0x9230a000",reason="dyld",requested-state="Y",state="Y",path="/usr/lib/libgcc_s.1.dylib",description="/usr/lib/libgcc_s.1.dylib",loaded_addr="0x9230a000",slide="-0x6dcf6000",prefix=""},time={now="1210290757.432771"} +=shlibs-added,shlib-info={num="4",name="libSystem.B.dylib",kind="-",dyld-addr="0x950aa000",reason="dyld",requested-state="Y",state="Y",path="/usr/lib/libSystem.B.dylib",description="/usr/lib/libSystem.B.dylib",loaded_addr="0x950aa000",slide="-0x6af56000",prefix="",commpage-objpath="/usr/lib/libSystem.B.dylib[LC_SEGMENT.__DATA.__commpage]"},time={now="1210290757.433091"} +=shlibs-added,shlib-info={num="5",name="libmathCommon.A.dylib",kind="-",dyld-addr="0x95018000",reason="dyld",requested-state="Y",state="Y",path="/usr/lib/system/libmathCommon.A.dylib",description="/usr/lib/system/libmathCommon.A.dylib",loaded_addr="0x95018000",slide="-0x6afe8000",prefix=""},time={now="1210290757.433390"} +*stopped,time={wallclock="1.02740",user="0.00379",system="0.00791",start="1210290756.408774",end="1210290757.436179"},reason="breakpoint-hit",commands="no",times="1",bkptno="1",thread-id="1" +''' + + test4 = '''=shlibs-added,shlib-info={num="2",name="qi",kind="-",dyld-addr="0x1000",reason="exec",requested-state="Y",state="Y",path="/Users/franklaub/bin/qi",description="/Users/franklaub/bin/qi",loaded_addr="",slide="0x0",prefix="",dsym-objpath="/Users/franklaub/bin/qi.dSYM/Contents/Resources/DWARF/qi"},time={now="1210290757.432413"} +^running +''' + test5 = '''=class,variable={frame={x="2"},frame={x="2"}, regs={"1","2","3"}} +^running +''' + test6 = '10^done,stack-args={frame={level="0",args={}}},time={wallclock="0.00006",user="0.00004",system="0.00002",start="1210530442.460765",end="1210530442.460825"}\n' + + run_test(test1) + run_test(test2) + run_test(test3) + run_test(test4) + run_test(test5) + run_test(test6) + + main() diff --git a/tester/rt/pygdb/spark.py b/tester/rt/pygdb/spark.py new file mode 100644 index 0000000..aab2d19 --- /dev/null +++ b/tester/rt/pygdb/spark.py @@ -0,0 +1,847 @@ +# Copyright (c) 1998-2002 John Aycock +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +__version__ = 'SPARK-0.7 (pre-alpha-7)' + +import re +import sys +import string + +def _namelist(instance): + namelist, namedict, classlist = [], {}, [instance.__class__] + for c in classlist: + for b in c.__bases__: + classlist.append(b) + for name in c.__dict__.keys(): + if not namedict.has_key(name): + namelist.append(name) + namedict[name] = 1 + return namelist + +class GenericScanner: + def __init__(self, flags=0): + pattern = self.reflect() + self.re = re.compile(pattern, re.VERBOSE|flags) + + self.index2func = {} + for name, number in self.re.groupindex.items(): + self.index2func[number-1] = getattr(self, 't_' + name) + + def makeRE(self, name): + doc = getattr(self, name).__doc__ + rv = '(?P<%s>%s)' % (name[2:], doc) + return rv + + def reflect(self): + rv = [] + for name in _namelist(self): + if name[:2] == 't_' and name != 't_default': + rv.append(self.makeRE(name)) + + rv.append(self.makeRE('t_default')) + return string.join(rv, '|') + + def error(self, s, pos): + print "Lexical error at position %s" % pos + raise SystemExit + + def position(self, newpos=None): + oldpos = self.pos + if newpos is not None: + self.pos = newpos + return self.string, oldpos + + def tokenize(self, s): + self.string = s + self.pos = 0 + n = len(s) + while self.pos < n: + m = self.re.match(s, self.pos) + if m is None: + self.error(s, self.pos) + + groups = m.groups() + self.pos = m.end() + for i in range(len(groups)): + if groups[i] is not None and self.index2func.has_key(i): + self.index2func[i](groups[i]) + + def t_default(self, s): + r'( . | \n )+' + print "Specification error: unmatched input" + raise SystemExit + +# +# Extracted from GenericParser and made global so that [un]picking works. +# +class _State: + def __init__(self, stateno, items): + self.T, self.complete, self.items = [], [], items + self.stateno = stateno + +class GenericParser: + # + # An Earley parser, as per J. Earley, "An Efficient Context-Free + # Parsing Algorithm", CACM 13(2), pp. 94-102. Also J. C. Earley, + # "An Efficient Context-Free Parsing Algorithm", Ph.D. thesis, + # Carnegie-Mellon University, August 1968. New formulation of + # the parser according to J. Aycock, "Practical Earley Parsing + # and the SPARK Toolkit", Ph.D. thesis, University of Victoria, + # 2001, and J. Aycock and R. N. Horspool, "Practical Earley + # Parsing", unpublished paper, 2001. + # + + def __init__(self, start): + self.rules = {} + self.rule2func = {} + self.rule2name = {} + self.collectRules() + self.augment(start) + self.ruleschanged = 1 + + _NULLABLE = '\e_' + _START = 'START' + _BOF = '|-' + + # + # When pickling, take the time to generate the full state machine; + # some information is then extraneous, too. Unfortunately we + # can't save the rule2func map. + # + def __getstate__(self): + if self.ruleschanged: + # + # XXX - duplicated from parse() + # + self.computeNull() + self.newrules = {} + self.new2old = {} + self.makeNewRules() + self.ruleschanged = 0 + self.edges, self.cores = {}, {} + self.states = { 0: self.makeState0() } + self.makeState(0, self._BOF) + # + # XXX - should find a better way to do this.. + # + changes = 1 + while changes: + changes = 0 + for k, v in self.edges.items(): + if v is None: + state, sym = k + if self.states.has_key(state): + self.goto(state, sym) + changes = 1 + rv = self.__dict__.copy() + for s in self.states.values(): + del s.items + del rv['rule2func'] + del rv['nullable'] + del rv['cores'] + return rv + + def __setstate__(self, D): + self.rules = {} + self.rule2func = {} + self.rule2name = {} + self.collectRules() + start = D['rules'][self._START][0][1][1] # Blech. + self.augment(start) + D['rule2func'] = self.rule2func + D['makeSet'] = self.makeSet_fast + self.__dict__ = D + + # + # A hook for GenericASTBuilder and GenericASTMatcher. Mess + # thee not with this; nor shall thee toucheth the _preprocess + # argument to addRule. + # + def preprocess(self, rule, func): return rule, func + + def addRule(self, doc, func, _preprocess=1): + fn = func + rules = string.split(doc) + + index = [] + for i in range(len(rules)): + if rules[i] == '::=': + index.append(i-1) + index.append(len(rules)) + + for i in range(len(index)-1): + lhs = rules[index[i]] + rhs = rules[index[i]+2:index[i+1]] + rule = (lhs, tuple(rhs)) + + if _preprocess: + rule, fn = self.preprocess(rule, func) + + if self.rules.has_key(lhs): + self.rules[lhs].append(rule) + else: + self.rules[lhs] = [ rule ] + self.rule2func[rule] = fn + self.rule2name[rule] = func.__name__[2:] + self.ruleschanged = 1 + + def collectRules(self): + for name in _namelist(self): + if name[:2] == 'p_': + func = getattr(self, name) + doc = func.__doc__ + self.addRule(doc, func) + + def augment(self, start): + rule = '%s ::= %s %s' % (self._START, self._BOF, start) + self.addRule(rule, lambda args: args[1], 0) + + def computeNull(self): + self.nullable = {} + tbd = [] + + for rulelist in self.rules.values(): + lhs = rulelist[0][0] + self.nullable[lhs] = 0 + for rule in rulelist: + rhs = rule[1] + if len(rhs) == 0: + self.nullable[lhs] = 1 + continue + # + # We only need to consider rules which + # consist entirely of nonterminal symbols. + # This should be a savings on typical + # grammars. + # + for sym in rhs: + if not self.rules.has_key(sym): + break + else: + tbd.append(rule) + changes = 1 + while changes: + changes = 0 + for lhs, rhs in tbd: + if self.nullable[lhs]: + continue + for sym in rhs: + if not self.nullable[sym]: + break + else: + self.nullable[lhs] = 1 + changes = 1 + + def makeState0(self): + s0 = _State(0, []) + for rule in self.newrules[self._START]: + s0.items.append((rule, 0)) + return s0 + + def finalState(self, tokens): + # + # Yuck. + # + if len(self.newrules[self._START]) == 2 and len(tokens) == 0: + return 1 + start = self.rules[self._START][0][1][1] + return self.goto(1, start) + + def makeNewRules(self): + worklist = [] + for rulelist in self.rules.values(): + for rule in rulelist: + worklist.append((rule, 0, 1, rule)) + + for rule, i, candidate, oldrule in worklist: + lhs, rhs = rule + n = len(rhs) + while i < n: + sym = rhs[i] + if not self.rules.has_key(sym) or \ + not self.nullable[sym]: + candidate = 0 + i = i + 1 + continue + + newrhs = list(rhs) + newrhs[i] = self._NULLABLE+sym + newrule = (lhs, tuple(newrhs)) + worklist.append((newrule, i+1, + candidate, oldrule)) + candidate = 0 + i = i + 1 + else: + if candidate: + lhs = self._NULLABLE+lhs + rule = (lhs, rhs) + if self.newrules.has_key(lhs): + self.newrules[lhs].append(rule) + else: + self.newrules[lhs] = [ rule ] + self.new2old[rule] = oldrule + + def typestring(self, token): + return None + + def error(self, token): + print "Syntax error at or near `%s' token" % token + raise SystemExit + + def parse(self, tokens): + sets = [ [(1,0), (2,0)] ] + self.links = {} + + if self.ruleschanged: + self.computeNull() + self.newrules = {} + self.new2old = {} + self.makeNewRules() + self.ruleschanged = 0 + self.edges, self.cores = {}, {} + self.states = { 0: self.makeState0() } + self.makeState(0, self._BOF) + + for i in xrange(len(tokens)): + sets.append([]) + + if sets[i] == []: + break + self.makeSet(tokens[i], sets, i) + else: + sets.append([]) + self.makeSet(None, sets, len(tokens)) + + #_dump(tokens, sets, self.states) + + finalitem = (self.finalState(tokens), 0) + if finalitem not in sets[-2]: + if len(tokens) > 0: + self.error(tokens[i-1], i, tokens) + else: + self.error(None) + + return self.buildTree(self._START, finalitem, + tokens, len(sets)-2) + + def isnullable(self, sym): + # + # For symbols in G_e only. If we weren't supporting 1.5, + # could just use sym.startswith(). + # + return self._NULLABLE == sym[0:len(self._NULLABLE)] + + def skip(self, (lhs, rhs), pos=0): + n = len(rhs) + while pos < n: + if not self.isnullable(rhs[pos]): + break + pos = pos + 1 + return pos + + def makeState(self, state, sym): + assert sym is not None + # + # Compute \epsilon-kernel state's core and see if + # it exists already. + # + kitems = [] + for rule, pos in self.states[state].items: + lhs, rhs = rule + if rhs[pos:pos+1] == (sym,): + kitems.append((rule, self.skip(rule, pos+1))) + core = kitems + + core.sort() + tcore = tuple(core) + if self.cores.has_key(tcore): + return self.cores[tcore] + # + # Nope, doesn't exist. Compute it and the associated + # \epsilon-nonkernel state together; we'll need it right away. + # + k = self.cores[tcore] = len(self.states) + K, NK = _State(k, kitems), _State(k+1, []) + self.states[k] = K + predicted = {} + + edges = self.edges + rules = self.newrules + for X in K, NK: + worklist = X.items + for item in worklist: + rule, pos = item + lhs, rhs = rule + if pos == len(rhs): + X.complete.append(rule) + continue + + nextSym = rhs[pos] + key = (X.stateno, nextSym) + if not rules.has_key(nextSym): + if not edges.has_key(key): + edges[key] = None + X.T.append(nextSym) + else: + edges[key] = None + if not predicted.has_key(nextSym): + predicted[nextSym] = 1 + for prule in rules[nextSym]: + ppos = self.skip(prule) + new = (prule, ppos) + NK.items.append(new) + # + # Problem: we know K needs generating, but we + # don't yet know about NK. Can't commit anything + # regarding NK to self.edges until we're sure. Should + # we delay committing on both K and NK to avoid this + # hacky code? This creates other problems.. + # + if X is K: + edges = {} + + if NK.items == []: + return k + + # + # Check for \epsilon-nonkernel's core. Unfortunately we + # need to know the entire set of predicted nonterminals + # to do this without accidentally duplicating states. + # + core = predicted.keys() + core.sort() + tcore = tuple(core) + if self.cores.has_key(tcore): + self.edges[(k, None)] = self.cores[tcore] + return k + + nk = self.cores[tcore] = self.edges[(k, None)] = NK.stateno + self.edges.update(edges) + self.states[nk] = NK + return k + + def goto(self, state, sym): + key = (state, sym) + if not self.edges.has_key(key): + # + # No transitions from state on sym. + # + return None + + rv = self.edges[key] + if rv is None: + # + # Target state isn't generated yet. Remedy this. + # + rv = self.makeState(state, sym) + self.edges[key] = rv + return rv + + def gotoT(self, state, t): + return [self.goto(state, t)] + + def gotoST(self, state, st): + rv = [] + for t in self.states[state].T: + if st == t: + rv.append(self.goto(state, t)) + return rv + + def add(self, set, item, i=None, predecessor=None, causal=None): + if predecessor is None: + if item not in set: + set.append(item) + else: + key = (item, i) + if item not in set: + self.links[key] = [] + set.append(item) + self.links[key].append((predecessor, causal)) + + def makeSet(self, token, sets, i): + cur, next = sets[i], sets[i+1] + + ttype = token is not None and self.typestring(token) or None + if ttype is not None: + fn, arg = self.gotoT, ttype + else: + fn, arg = self.gotoST, token + + for item in cur: + ptr = (item, i) + state, parent = item + add = fn(state, arg) + for k in add: + if k is not None: + self.add(next, (k, parent), i+1, ptr) + nk = self.goto(k, None) + if nk is not None: + self.add(next, (nk, i+1)) + + if parent == i: + continue + + for rule in self.states[state].complete: + lhs, rhs = rule + for pitem in sets[parent]: + pstate, pparent = pitem + k = self.goto(pstate, lhs) + if k is not None: + why = (item, i, rule) + pptr = (pitem, parent) + self.add(cur, (k, pparent), + i, pptr, why) + nk = self.goto(k, None) + if nk is not None: + self.add(cur, (nk, i)) + + def makeSet_fast(self, token, sets, i): + # + # Call *only* when the entire state machine has been built! + # It relies on self.edges being filled in completely, and + # then duplicates and inlines code to boost speed at the + # cost of extreme ugliness. + # + cur, next = sets[i], sets[i+1] + ttype = token is not None and self.typestring(token) or None + + for item in cur: + ptr = (item, i) + state, parent = item + if ttype is not None: + k = self.edges.get((state, ttype), None) + if k is not None: + #self.add(next, (k, parent), i+1, ptr) + #INLINED --v + new = (k, parent) + key = (new, i+1) + if new not in next: + self.links[key] = [] + next.append(new) + self.links[key].append((ptr, None)) + #INLINED --^ + #nk = self.goto(k, None) + nk = self.edges.get((k, None), None) + if nk is not None: + #self.add(next, (nk, i+1)) + #INLINED --v + new = (nk, i+1) + if new not in next: + next.append(new) + #INLINED --^ + else: + add = self.gotoST(state, token) + for k in add: + if k is not None: + self.add(next, (k, parent), i+1, ptr) + #nk = self.goto(k, None) + nk = self.edges.get((k, None), None) + if nk is not None: + self.add(next, (nk, i+1)) + + if parent == i: + continue + + for rule in self.states[state].complete: + lhs, rhs = rule + for pitem in sets[parent]: + pstate, pparent = pitem + #k = self.goto(pstate, lhs) + k = self.edges.get((pstate, lhs), None) + if k is not None: + why = (item, i, rule) + pptr = (pitem, parent) + #self.add(cur, (k, pparent), + # i, pptr, why) + #INLINED --v + new = (k, pparent) + key = (new, i) + if new not in cur: + self.links[key] = [] + cur.append(new) + self.links[key].append((pptr, why)) + #INLINED --^ + #nk = self.goto(k, None) + nk = self.edges.get((k, None), None) + if nk is not None: + #self.add(cur, (nk, i)) + #INLINED --v + new = (nk, i) + if new not in cur: + cur.append(new) + #INLINED --^ + + def predecessor(self, key, causal): + for p, c in self.links[key]: + if c == causal: + return p + assert 0 + + def causal(self, key): + links = self.links[key] + if len(links) == 1: + return links[0][1] + choices = [] + rule2cause = {} + for p, c in links: + rule = c[2] + choices.append(rule) + rule2cause[rule] = c + return rule2cause[self.ambiguity(choices)] + + def deriveEpsilon(self, nt): + if len(self.newrules[nt]) > 1: + rule = self.ambiguity(self.newrules[nt]) + else: + rule = self.newrules[nt][0] + #print rule + + rhs = rule[1] + attr = [None] * len(rhs) + + for i in range(len(rhs)-1, -1, -1): + attr[i] = self.deriveEpsilon(rhs[i]) + return self.rule2func[self.new2old[rule]](attr) + + def buildTree(self, nt, item, tokens, k): + state, parent = item + + choices = [] + for rule in self.states[state].complete: + if rule[0] == nt: + choices.append(rule) + rule = choices[0] + if len(choices) > 1: + rule = self.ambiguity(choices) + #print rule + + rhs = rule[1] + attr = [None] * len(rhs) + + for i in range(len(rhs)-1, -1, -1): + sym = rhs[i] + if not self.newrules.has_key(sym): + if sym != self._BOF: + attr[i] = tokens[k-1] + key = (item, k) + item, k = self.predecessor(key, None) + #elif self.isnullable(sym): + elif self._NULLABLE == sym[0:len(self._NULLABLE)]: + attr[i] = self.deriveEpsilon(sym) + else: + key = (item, k) + why = self.causal(key) + attr[i] = self.buildTree(sym, why[0], + tokens, why[1]) + item, k = self.predecessor(key, why) + return self.rule2func[self.new2old[rule]](attr) + + def ambiguity(self, rules): + # + # XXX - problem here and in collectRules() if the same rule + # appears in >1 method. Also undefined results if rules + # causing the ambiguity appear in the same method. + # + sortlist = [] + name2index = {} + for i in range(len(rules)): + lhs, rhs = rule = rules[i] + name = self.rule2name[self.new2old[rule]] + sortlist.append((len(rhs), name)) + name2index[name] = i + sortlist.sort() + list = map(lambda (a,b): b, sortlist) + return rules[name2index[self.resolve(list)]] + + def resolve(self, list): + # + # Resolve ambiguity in favor of the shortest RHS. + # Since we walk the tree from the top down, this + # should effectively resolve in favor of a "shift". + # + return list[0] + +# +# GenericASTBuilder automagically constructs a concrete/abstract syntax tree +# for a given input. The extra argument is a class (not an instance!) +# which supports the "__setslice__" and "__len__" methods. +# +# XXX - silently overrides any user code in methods. +# + +class GenericASTBuilder(GenericParser): + def __init__(self, AST, start): + GenericParser.__init__(self, start) + self.AST = AST + + def preprocess(self, rule, func): + rebind = lambda lhs, self=self: \ + lambda args, lhs=lhs, self=self: \ + self.buildASTNode(args, lhs) + lhs, rhs = rule + return rule, rebind(lhs) + + def buildASTNode(self, args, lhs): + children = [] + for arg in args: + if isinstance(arg, self.AST): + children.append(arg) + else: + children.append(self.terminal(arg)) + return self.nonterminal(lhs, children) + + def terminal(self, token): return token + + def nonterminal(self, type, args): + rv = self.AST(type) + rv[:len(args)] = args + return rv + +# +# GenericASTTraversal is a Visitor pattern according to Design Patterns. For +# each node it attempts to invoke the method n_<node type>, falling +# back onto the default() method if the n_* can't be found. The preorder +# traversal also looks for an exit hook named n_<node type>_exit (no default +# routine is called if it's not found). To prematurely halt traversal +# of a subtree, call the prune() method -- this only makes sense for a +# preorder traversal. Node type is determined via the typestring() method. +# + +class GenericASTTraversalPruningException: + pass + +class GenericASTTraversal: + def __init__(self, ast): + self.ast = ast + + def typestring(self, node): + return node.type + + def prune(self): + raise GenericASTTraversalPruningException + + def preorder(self, node=None): + if node is None: + node = self.ast + + try: + name = 'n_' + self.typestring(node) + if hasattr(self, name): + func = getattr(self, name) + func(node) + else: + self.default(node) + except GenericASTTraversalPruningException: + return + + for kid in node: + self.preorder(kid) + + name = name + '_exit' + if hasattr(self, name): + func = getattr(self, name) + func(node) + + def postorder(self, node=None): + if node is None: + node = self.ast + + for kid in node: + self.postorder(kid) + + name = 'n_' + self.typestring(node) + if hasattr(self, name): + func = getattr(self, name) + func(node) + else: + self.default(node) + + + def default(self, node): + pass + +# +# GenericASTMatcher. AST nodes must have "__getitem__" and "__cmp__" +# implemented. +# +# XXX - makes assumptions about how GenericParser walks the parse tree. +# + +class GenericASTMatcher(GenericParser): + def __init__(self, start, ast): + GenericParser.__init__(self, start) + self.ast = ast + + def preprocess(self, rule, func): + rebind = lambda func, self=self: \ + lambda args, func=func, self=self: \ + self.foundMatch(args, func) + lhs, rhs = rule + rhslist = list(rhs) + rhslist.reverse() + + return (lhs, tuple(rhslist)), rebind(func) + + def foundMatch(self, args, func): + func(args[-1]) + return args[-1] + + def match_r(self, node): + self.input.insert(0, node) + children = 0 + + for child in node: + if children == 0: + self.input.insert(0, '(') + children = children + 1 + self.match_r(child) + + if children > 0: + self.input.insert(0, ')') + + def match(self, ast=None): + if ast is None: + ast = self.ast + self.input = [] + + self.match_r(ast) + self.parse(self.input) + + def resolve(self, list): + # + # Resolve ambiguity in favor of the longest RHS. + # + return list[-1] + +def _dump(tokens, sets, states): + for i in range(len(sets)): + print 'set', i + for item in sets[i]: + print '\t', item + for (lhs, rhs), pos in states[item[0]].items: + print '\t\t', lhs, '::=', + print string.join(rhs[:pos]), + print '.', + print string.join(rhs[pos:]) + if i < len(tokens): + print + print 'token', str(tokens[i]) + print diff --git a/tester/rt/report.py b/tester/rt/report.py new file mode 100644 index 0000000..1aa1f35 --- /dev/null +++ b/tester/rt/report.py @@ -0,0 +1,185 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# RTEMS Testing Reports +# + +import datetime +import os +import threading + +from rtemstoolkit import error +from rtemstoolkit import log +from rtemstoolkit import path + +class report(object): + '''RTEMS Testing report.''' + + def __init__(self, total): + self.lock = threading.Lock() + self.total = total + self.total_len = len(str(total)) + self.passed = 0 + self.failed = 0 + self.timeouts = 0 + self.invalids = 0 + self.invalid_tests = 0 + self.results = {} + self.name_max_len = 0 + + def __str__(self): + msg = 'Passed: %*d%s' % (self.total_len, self.passed, os.linesep) + msg += 'Failed: %*d%s' % (self.total_len, self.failed, os.linesep) + msg += 'Timeouts: %*d%s' % (self.total_len, self.timeouts, os.linesep) + msg += 'Invalid: %*d%s' % (self.total_len, self.invalids, os.linesep) + return msg + + def set_invalid_tests(self, invalid_tests): + self.invalid_tests = invalid_tests + + def start(self, index, total, name, executable, bsp_arch, bsp): + header = '[%*d/%*d] p:%-*d f:%-*d t:%-*d i:%-*d | %s/%s: %s' % \ + (len(str(total)), index, + len(str(total)), total, + len(str(total)), self.passed, + len(str(total)), self.failed, + len(str(total)), self.timeouts, + len(str(total)), self.invalids, + bsp_arch, + bsp, + path.basename(executable)) + self.lock.acquire() + if name in self.results: + self.lock.release() + raise error.general('duplicate test: %s' % (name)) + self.results[name] = { 'index': index, + 'bsp': bsp, + 'bsp_arch': bsp_arch, + 'exe': executable, + 'start': datetime.datetime.now(), + 'end': None, + 'result': None, + 'output': None, + 'header': header } + + self.lock.release() + log.notice(header, stdout_only = True) + + def end(self, name, output): + start = False + end = False + timeout = False + prefixed_output = [] + for line in output: + if line[0] == ']': + if line[1].startswith('*** '): + if line[1][4:].startswith('END OF '): + end = True + if line[1][4:].startswith('TIMEOUT TIMEOUT'): + timeout = True + else: + start = True + prefixed_output += [line[0] + ' ' + line[1]] + self.lock.acquire() + if name not in self.results: + self.lock.release() + raise error.general('test report missing: %s' % (name)) + if self.results[name]['end'] is not None: + self.lock.release() + raise error.general('test already finished: %s' % (name)) + self.results[name]['end'] = datetime.datetime.now() + if start and end: + status = 'passed' + self.passed += 1 + elif timeout: + status = 'timeout' + self.timeouts += 1 + elif start: + if not end: + status = 'failed' + self.failed += 1 + else: + if self.invalid_tests and path.basename(name) in self.invalid_tests: + status = 'passed' + self.passed += 1 + else: + status = 'invalid' + self.invalids += 1 + self.results[name]['result'] = status + self.results[name]['output'] = prefixed_output + if self.name_max_len < len(path.basename(name)): + self.name_max_len = len(path.basename(name)) + self.lock.release() + + def log(self, name, mode): + if mode != 'none': + self.lock.acquire() + if name not in self.results: + self.lock.release() + raise error.general('test report missing: %s' % (name)) + result = self.results[name]['result'] + time = self.results[name]['end'] - self.results[name]['start'] + if mode != 'none': + header = self.results[name]['header'] + if mode == 'all' or result != 'passed': + output = self.results[name]['output'] + else: + output = None + self.lock.release() + if header: + log.output(header) + if output: + log.output(output) + if header: + log.output('Result: %-10s Time: %s' % (result, str(time))) + + def summary(self): + def show_state(results, state, max_len): + for name in results: + if results[name]['result'] == state: + log.output(' %s' % (path.basename(name))) + log.output() + log.notice('Passed: %*d' % (self.total_len, self.passed)) + log.notice('Failed: %*d' % (self.total_len, self.failed)) + log.notice('Timeouts: %*d' % (self.total_len, self.timeouts)) + log.notice('Invalid: %*d' % (self.total_len, self.invalids)) + log.output('----------%s' % ('-' * self.total_len)) + log.notice('Total: %*d' % (self.total_len, self.total)) + log.output() + if self.failed: + log.output('Failures:') + show_state(self.results, 'failed', self.name_max_len) + if self.timeouts: + log.output('Timeouts:') + show_state(self.results, 'timeout', self.name_max_len) + if self.invalids: + log.output('Invalid:') + show_state(self.results, 'invalid', self.name_max_len) diff --git a/tester/rt/stty.py b/tester/rt/stty.py new file mode 100644 index 0000000..d059b40 --- /dev/null +++ b/tester/rt/stty.py @@ -0,0 +1,567 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# RTEMS Testing Consoles +# + +import os +import sys +import termios + +from rtemstoolkit import error +from rtemstoolkit import options +from rtemstoolkit import path + +def save(): + if not options.host_windows: + try: + sin = termios.tcgetattr(sys.stdin) + sout = termios.tcgetattr(sys.stdout) + serr = termios.tcgetattr(sys.stderr) + return sin, sout, serr + except: + pass + return None + +def restore(attributes): + if attributes is not None: + termios.tcsetattr(sys.stdin, termios.TCSANOW, attributes[0]) + termios.tcsetattr(sys.stdout, termios.TCSANOW, attributes[1]) + termios.tcsetattr(sys.stderr, termios.TCSANOW, attributes[2]) + +class tty: + + def __init__(self, dev): + if options.host_windows: + raise error.general('termios not support on host') + self.dev = dev + self.default_attr = None + self.fd = None + self.if_on = False + if options.host_windows: + raise error.general('TTY consoles not supported on Windows.') + if not path.exists(dev): + raise error.general('dev not found: %s' % (dev)) + try: + self.fd = open(dev, 'rw') + except IOError, ioe: + raise error.general('opening tty dev: %s: %s' % (dev, ioe)) + except: + raise error.general('opening tty dev: %s: unknown' % (dev)) + try: + self.default_attr = termios.tcgetattr(self.fd) + except: + raise error.general('cannot get termios attrs: %s' % (dev)) + self.attr = self.default_attr + + def __del__(self): + if self.fd and self.default_attr: + try: + self.fd.close() + except: + pass + + def __str__(self): + def _input(attr): + s = '' + if attr & termios.IGNBRK: + s += ' IGNBRK' + if attr & termios.BRKINT: + s += ' BRKINT' + if attr & termios.IGNPAR: + s += ' IGNPAR' + if attr & termios.PARMRK: + s += ' PARMRK' + if attr & termios.INPCK: + s += ' INPCK' + if attr & termios.ISTRIP: + s += ' ISTRIP' + if attr & termios.INLCR: + s += ' INLCR' + if attr & termios.IGNCR: + s += ' IGNCR' + if attr & termios.IXON: + s += ' IXON' + if attr & termios.IXOFF: + s += ' IXOFF' + if attr & termios.IXANY: + s += ' IXANY' + if attr & termios.IMAXBEL: + s += ' IMAXBEL' + return s + + def _output(attr): + s = '' + if attr & termios.OPOST: + s += ' OPOST' + if attr & termios.ONLCR: + s += ' ONLCR' + if attr & termios.OCRNL: + s += ' OCRNL' + if attr & termios.TABDLY: + s += ' TABDLY' + if attr & termios.TAB0: + s += ' TAB0' + if attr & termios.TAB3: + s += ' TAB3' + if attr & termios.ONOCR: + s += ' ONOCR' + if attr & termios.ONLRET: + s += ' ONLRET' + return s + + def _control(attr): + s = '' + if (attr & termios.CSIZE) == termios.CS5: + s += ' CS5' + if (attr & termios.CSIZE) == termios.CS6: + s += ' CS6' + if (attr & termios.CSIZE) == termios.CS7: + s += ' CS7' + if (attr & termios.CSIZE) == termios.CS8: + s += ' CS8' + if attr & termios.CSTOPB: + s += ' CSTOPB' + if attr & termios.CREAD: + s += ' CREAD' + if attr & termios.PARENB: + s += ' PARENB' + if attr & termios.PARODD: + s += ' PARODD' + if attr & termios.HUPCL: + s += ' HUPCL' + if attr & termios.CLOCAL: + s += ' CLOCAL' + if attr & termios.CRTSCTS: + s += ' CRTSCTS' + return s + + def _local(attr): + s = '' + if attr & termios.ECHOKE: + s += ' ECHOKE' + if attr & termios.ECHOE: + s += ' ECHOE' + if attr & termios.ECHO: + s += ' ECHO' + if attr & termios.ECHONL: + s += ' ECHONL' + if attr & termios.ECHOPRT: + s += ' ECHOPRT' + if attr & termios.ECHOCTL: + s += ' ECHOCTL' + if attr & termios.ISIG: + s += ' ISIG' + if attr & termios.ICANON: + s += ' ICANON' + if attr & termios.IEXTEN: + s += ' IEXTEN' + if attr & termios.TOSTOP: + s += ' TOSTOP' + if attr & termios.FLUSHO: + s += ' FLUSHO' + if attr & termios.PENDIN: + s += ' PENDIN' + if attr & termios.NOFLSH: + s += ' NOFLSH' + return s + + def _baudrate(attr): + if attr == termios.B0: + s = 'B0' + elif attr == termios.B50: + s = 'B50' + elif attr == termios.B75: + s = 'B75' + elif attr == termios.B110: + s = 'B110' + elif attr == termios.B134: + s = 'B134' + elif attr == termios.B150: + s = 'B150' + elif attr == termios.B200: + s = 'B200' + elif attr == termios.B300: + s = 'B300' + elif attr == termios.B600: + s = 'B600' + elif attr == termios.B1800: + s = 'B1800' + elif attr == termios.B1200: + s = 'B1200' + elif attr == termios.B2400: + s = 'B2400' + elif attr == termios.B4800: + s = 'B4800' + elif attr == termios.B9600: + s = 'B9600' + elif attr == termios.B19200: + s = 'B19200' + elif attr == termios.B38400: + s = 'B38400' + elif attr == termios.B57600: + s = 'B57600' + elif attr == termios.B115200: + s = 'B115200' + elif attr == termios.B230400: + s = 'B230400' + elif attr == termios.B460800: + s = 'B460800' + else: + s = 'unknown' + return s + + if self.attr is None: + return 'None' + s = 'iflag: %s' % (_input(self.attr[0])) + s += os.linesep + 'oflag: %s' % (_output(self.attr[1])) + s += os.linesep + 'cflag: %s' % (_control(self.attr[2])) + s += os.linesep + 'lflag: %s' % (_local(self.attr[3])) + s += os.linesep + 'ispeed: %s' % (_baudrate(self.attr[4])) + s += os.linesep + 'ospeed: %s' % (_baudrate(self.attr[5])) + return s + + def _update(self): + self.off() + try: + termios.tcflush(self.fd, termios.TCIOFLUSH) + #attr = self.attr + #attr[0] = termios.IGNPAR; + #attr[1] = 0 + #attr[2] = termios.CRTSCTS | termios.CS8 | termios.CREAD; + #attr[3] = 0 + #attr[6][termios.VMIN] = 1 + #attr[6][termios.VTIME] = 2 + #termios.tcsetattr(self.fd, termios.TCSANOW, attr) + termios.tcsetattr(self.fd, termios.TCSANOW, self.attr) + termios.tcflush(self.fd, termios.TCIOFLUSH) + except: + raise + if self.is_on: + self.on() + + def _baudrate_mask(self, flag): + if flag == 'B0': + mask = termios.B0 + self.attr[5] = termios.B0 + elif flag == 'B50': + mask = termios.B50 + elif flag == 'B75': + mask = termios.B75 + elif flag == 'B110': + mask = termios.B110 + elif flag == 'B134': + mask = termios.B134 + elif flag == 'B150': + mask = termios.B150 + elif flag == 'B200': + mask = termios.B200 + elif flag == 'B300': + mask = termios.B300 + elif flag == 'B600': + mask = termios.B600 + elif flag == 'B1800': + mask = termios.B1800 + elif flag == 'B1200': + mask = termios.B1200 + elif flag == 'B2400': + mask = termios.B2400 + elif flag == 'B4800': + mask = termios.B4800 + elif flag == 'B9600': + mask = termios.B9600 + elif flag == 'B19200': + mask = termios.B19200 + elif flag == 'B38400': + mask = termios.B38400 + elif flag == 'B57600': + mask = termios.B57600 + elif flag == 'B115200': + mask = termios.B115200 + elif flag == 'B230400': + mask = termios.B230400 + elif flag == 'B460800': + mask = termios.B460800 + else: + mask = None + return mask + + def _input_mask(self, flag): + if flag == 'IGNBRK': + mask = termios.IGNBRK + elif flag == 'BRKINT': + mask = termios.BRKINT + elif flag == 'IGNPAR': + mask = termios.IGNPAR + elif flag == 'PARMRK': + mask = termios.PARMRK + elif flag == 'INPCK': + mask = termios.INPCK + elif flag == 'ISTRIP': + mask = termios.ISTRIP + elif flag == 'INLCR': + mask = termios.INLCR + elif flag == 'IGNCR': + mask = termios.IGNCR + elif flag == 'IXON': + mask = termios.IXON + elif flag == 'IXOFF': + mask = termios.IXOFF + elif flag == 'IXANY': + mask = termios.IXANY + elif flag == 'IMAXBEL': + mask = termios.IMAXBEL + else: + mask = None + return mask + + def _output_mask(self, flag): + if flag == 'OPOST': + mask = termios.OPOST + elif flag == 'ONLCR': + mask = termios.ONLCR + elif flag == 'OCRNL': + mask = termios.OCRNL + elif flag == 'TABDLY': + mask = termios.TABDLY + elif flag == 'TAB0': + mask = termios.TAB0 + elif flag == 'TAB3': + mask = termios.TAB3 + elif flag == 'ONOCR': + mask = termios.ONOCR + elif flag == 'ONLRET': + mask = termios.ONLRET + else: + mask = None + return mask + + def _control_mask(self, flag): + if flag == 'CSTOPB': + mask = termios.CSTOPB + elif flag == 'CREAD': + mask = termios.CREAD + elif flag == 'PARENB': + mask = termios.PARENB + elif flag == 'PARODD': + mask = termios.PARODD + elif flag == 'HUPCL': + mask = termios.HUPCL + elif flag == 'CLOCAL': + mask = termios.CLOCAL + elif flag == 'CRTSCTS': + mask = termios.CRTSCTS + else: + mask = None + return mask + + def _local_mask(self, flag): + if flag == 'ECHOKE': + mask = termios.ECHOKE + elif flag == 'ECHOE': + mask = termios.ECHOE + elif flag == 'ECHO': + mask = termios.ECHO + elif flag == 'ECHONL': + mask = termios.ECHONL + elif flag == 'ECHOPRT': + mask = termios.ECHOPRT + elif flag == 'ECHOCTL': + mask = termios.ECHOCTL + elif flag == 'ISIG': + mask = termios.ISIG + elif flag == 'ICANON': + mask = termios.ICANON + elif flag == 'IEXTEN': + mask = termios.IEXTEN + elif flag == 'TOSTOP': + mask = termios.TOSTOP + elif flag == 'FLUSHO': + mask = termios.FLUSHO + elif flag == 'PENDIN': + mask = termios.PENDIN + elif flag == 'NOFLSH': + mask = termios.NOFLSH + else: + mask = None + return mask + + def _set(self, index, mask, state): + if state: + self.attr[index] = self.attr[index] | mask + else: + self.attr[index] = self.attr[index] & ~mask + + def off(self): + if self.fd: + try: + termios.tcflow(self.fd, termios.TCOOFF) + except: + pass + try: + termios.tcflow(self.fd, termios.TCIOFF) + except: + pass + self.is_on = False + + def on(self): + if self.fd: + try: + termios.tcflow(self.fd, termios.TCOON) + except: + pass + try: + termios.tcflow(self.fd, termios.TCION) + except: + pass + self.is_on = True + + def baudrate(self, flag): + mask = self._baudrate_mask(flag) + if mask: + self.attr[4] = mask + self.attr[5] = mask + else: + raise error.general('invalid setting: %s' % (flag)) + self._update() + + def input(self, flag, on): + mask = self._input_mask(flag) + if mask is None: + raise error.general('invalid input flag: %s' % (flag)) + self._set(0, mask, on) + self._update() + + def output(self, flag, on): + mask = self._output_mask(flag) + if mask is None: + raise error.general('invalid output flag: %s' % (flag)) + self._set(1, mask, on) + self._update() + + def control(self, flag, on): + mask = self._control_mask(flag) + if mask is None: + raise error.general('invalid control flag: %s' % (flag)) + self._set(2, mask, on) + self._update() + + def local(self, flag, on): + mask = self._local_mask(flag) + if mask is None: + raise error.general('invalid local flag: %s' % (flag)) + self._set(3, mask, on) + self._update() + + def vmin(self, _vmin): + self.attr[6][termios.VMIN] = _vmin + + def vtime(self, _vtime): + self.attr[6][termios.VTIME] = _vtime + + def set(self, flags): + for f in flags.split(','): + if len(f) < 2: + raise error.general('invalid flag: %s' % (f)) + if f[0] == '~': + on = False + flag = f[1:] + else: + on = True + flag = f + if f.startswith('VMIN'): + vs = f.split('=') + if len(vs) != 2: + raise error.general('invalid vmin flag: %s' % (f)) + try: + _vmin = int(vs[1]) + except: + raise error.general('invalid vmin flag: %s' % (f)) + self.vmin(_vmin) + continue + if f.startswith('VTIME'): + vs = f.split('=') + if len(vs) != 2: + raise error.general('invalid vtime flag: %s' % (f)) + try: + _vtime = int(vs[1]) + except: + raise error.general('invalid vtime flag: %s' % (f)) + self.vtime(_vtime) + continue + mask = self._baudrate_mask(flag) + if mask: + if not on: + raise error.general('baudrates are not flags: %s' % (f)) + self.attr[4] = mask + self.attr[5] = mask + continue + mask = self._input_mask(flag) + if mask: + self._set(0, mask, on) + continue + mask = self._output_mask(flag) + if mask: + self._set(1, mask, on) + continue + mask = self._control_mask(flag) + if mask: + self._set(2, mask, on) + continue + mask = self._local_mask(flag) + if mask: + self._set(3, mask, on) + continue + raise error.general('unknown tty flag: %s' % (f)) + self._update() + +if __name__ == "__main__": + if len(sys.argv) == 2: + t = tty(sys.argv[1]) + t.baudrate('B115200') + t.input('BRKINT', False) + t.input('IGNBRK', True) + t.input('IGNCR', True) + t.local('ICANON', False) + t.local('ISIG', False) + t.local('IEXTEN', False) + t.local('ECHO', False) + t.control('CLOCAL', True) + t.control('CRTSCTS', False) + t.vmin(1) + t.vtime(2) + print t + t.set('B115200,~BRKINT,IGNBRK,IGNCR,~ICANON,~ISIG,~IEXTEN,~ECHO,CLOCAL,~CRTSCTS') + print t + t.on() + while True: + c = t.fd.read(1) + sys.stdout.write(c) diff --git a/tester/rt/test.py b/tester/rt/test.py new file mode 100644 index 0000000..15da4ee --- /dev/null +++ b/tester/rt/test.py @@ -0,0 +1,304 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +import copy +import datetime +import os +import sys +import threading +import time + +from rtemstoolkit import error +from rtemstoolkit import log +from rtemstoolkit import path + +import config +import console +import options +import report +import version + +def stacktraces(): + import traceback + code = [] + for threadId, stack in sys._current_frames().items(): + code.append("\n# thread-id: %s" % threadId) + for filename, lineno, name, line in traceback.extract_stack(stack): + code.append('file: "%s", line %d, in %s' % (filename, lineno, name)) + if line: + code.append(" %s" % (line.strip())) + return '\n'.join(code) + +class test(object): + def __init__(self, index, total, report, executable, rtems_tools, bsp, bsp_config, opts): + self.index = index + self.total = total + self.report = report + self.bsp = bsp + self.bsp_config = bsp_config + self.opts = copy.copy(opts) + self.opts.defaults['test_index'] = str(index) + self.opts.defaults['test_total'] = str(total) + self.opts.defaults['bsp'] = bsp + self.opts.defaults['bsp_arch'] = '%%{%s_arch}' % (bsp) + self.opts.defaults['bsp_opts'] = '%%{%s_opts}' % (bsp) + if not path.isfile(executable): + raise error.general('cannot find executable: %s' % (executable)) + self.opts.defaults['test_executable'] = executable + if rtems_tools: + rtems_tools_bin = path.join(rtems_tools, 'bin') + if not path.isdir(rtems_tools_bin): + raise error.general('cannot find RTEMS tools path: %s' % (rtems_tools_bin)) + self.opts.defaults['rtems_tools'] = rtems_tools_bin + self.config = config.file(report, bsp_config, self.opts) + +class test_run(object): + def __init__(self, index, total, report, executable, rtems_tools, bsp, bsp_config, opts): + self.test = None + self.result = None + self.start_time = None + self.end_time = None + self.index = copy.copy(index) + self.total = total + self.report = report + self.executable = copy.copy(executable) + self.rtems_tools = rtems_tools + self.bsp = bsp + self.bsp_config = bsp_config + self.opts = opts + + def runner(self): + self.start_time = datetime.datetime.now() + try: + self.test = test(self.index, self.total, self.report, + self.executable, self.rtems_tools, + self.bsp, self.bsp_config, + self.opts) + except KeyboardInterrupt: + pass + except: + self.result = sys.exc_info() + self.end_time = datetime.datetime.now() + + def run(self): + self.thread = threading.Thread(target = self.runner, + name = 'test[%s]' % path.basename(self.executable)) + self.thread.start() + + def is_alive(self): + return self.thread and self.thread.is_alive() + + def reraise(self): + if self.result is not None: + raise self.result[0], self.result[1], self.result[2] + +def find_executables(paths): + executables = [] + for p in paths: + if path.isfile(p): + executables += [p] + elif path.isdir(p): + for root, dirs, files in os.walk(p, followlinks = True): + for f in files: + if f.lower().endswith('.exe'): + executables += [path.join(root, f)] + return sorted(executables) + +def report_finished(reports, report_mode, reporting, finished, job_trace): + processing = True + while processing: + processing = False + reported = [] + for tst in finished: + if tst not in reported and \ + (reporting < 0 or tst.index == reporting): + if job_trace: + log.notice('}} %*d: %s: %s (%d)' % (len(str(tst.total)), tst.index, + path.basename(tst.executable), + 'reporting', + reporting)) + processing = True + reports.log(tst.executable, report_mode) + reported += [tst] + reporting += 1 + finished[:] = [t for t in finished if t not in reported] + if len(reported): + del reported[:] + if job_trace: + print '}} threading:', threading.active_count() + for t in threading.enumerate(): + print '}} ', t.name + return reporting + +def _job_trace(tst, msg, total, exe, active, reporting): + s = '' + for a in active: + s += ' %d:%s' % (a.index, path.basename(a.executable)) + log.notice('}} %*d: %s: %s (%d %d %d%s)' % (len(str(tst.total)), tst.index, + path.basename(tst.executable), + msg, + reporting, total, exe, s)) + +def list_bsps(opts): + path_ = opts.defaults.expand('%%{_configdir}/bsps/*.mc') + bsps = path.collect_files(path_) + log.notice(' BSP List:') + for bsp in bsps: + log.notice(' %s' % (path.basename(bsp[:-3]))) + raise error.exit() + +def run(command_path = None): + import sys + stdtty = console.save() + opts = None + try: + optargs = { '--rtems-tools': 'The path to the RTEMS tools', + '--rtems-bsp': 'The RTEMS BSP to run the test on', + '--report-mode': 'Reporting modes, failures (default),all,none', + '--list-bsps': 'List the supported BSPs', + '--debug-trace': 'Debug trace based on specific flags', + '--stacktrace': 'Dump a stack trace on a user termination (^C)' } + opts = options.load(sys.argv, + optargs = optargs, + command_path = command_path) + log.notice('RTEMS Testing - Tester, v%s' % (version.str())) + if opts.find_arg('--list-bsps'): + list_bsps(opts) + opts.log_info() + debug_trace = opts.find_arg('--debug-trace') + if debug_trace: + debug_trace = debug_trace[1] + else: + debug_trace = '' + opts.defaults['debug_trace'] = debug_trace + job_trace = 'jobs' in debug_trace.split(',') + rtems_tools = opts.find_arg('--rtems-tools') + if rtems_tools: + rtems_tools = rtems_tools[1] + bsp = opts.find_arg('--rtems-bsp') + if bsp is None: + raise error.general('no RTEMS BSP provided') + opts.defaults.load('%%{_configdir}/bsps/%s.mc' % (bsp[1])) + bsp = opts.defaults.get('%{bsp}') + if not bsp: + raise error.general('BSP definition (%{bsp}) not found in the global map') + bsp = bsp[2] + if not opts.defaults.set_read_map(bsp): + raise error.general('no BSP map found') + bsp_script = opts.defaults.get(bsp) + if not bsp_script: + raise error.general('BSP script not found: %s' % (bsp)) + bsp_config = opts.defaults.expand(opts.defaults[bsp]) + report_mode = opts.find_arg('--report-mode') + if report_mode: + if report_mode[1] != 'failures' and \ + report_mode[1] != 'all' and \ + report_mode[1] != 'none': + raise error.general('invalid report mode') + report_mode = report_mode[1] + else: + report_mode = 'failures' + executables = find_executables(opts.params()) + if len(executables) == 0: + raise error.general('no executbles supplied') + start_time = datetime.datetime.now() + total = len(executables) + reports = report.report(total) + invalid_tests = opts.defaults['invalid_tests'] + if invalid_tests: + reports.set_invalid_tests([l.strip() for l in invalid_tests.splitlines()]) + reporting = 1 + jobs = int(opts.jobs(opts.defaults['_ncpus'])) + exe = 0 + tests = [] + finished = [] + if jobs > len(executables): + jobs = len(executables) + while exe < total or len(tests) > 0: + if exe < total and len(tests) < jobs: + tst = test_run(exe + 1, total, reports, + executables[exe], + rtems_tools, bsp, bsp_config, + opts) + exe += 1 + tests += [tst] + if job_trace: + _job_trace(tst, 'create', + total, exe, tests, reporting) + tst.run() + else: + dead = [t for t in tests if not t.is_alive()] + tests[:] = [t for t in tests if t not in dead] + for tst in dead: + if job_trace: + _job_trace(tst, 'dead', + total, exe, tests, reporting) + finished += [tst] + tst.reraise() + del dead + if len(tests) >= jobs or exe >= total: + time.sleep(0.250) + if len(finished): + reporting = report_finished(reports, + report_mode, + reporting, + finished, + job_trace) + finished_time = datetime.datetime.now() + reporting = report_finished(reports, report_mode, + reporting, finished, job_trace) + if reporting < total: + log.warning('finished jobs does match: %d' % (reporting)) + report_finished(reports, report_mode, -1, finished, job_trace) + reports.summary() + end_time = datetime.datetime.now() + log.notice('Testing time: %s' % (str(end_time - start_time))) + except error.general, gerr: + print gerr + sys.exit(1) + except error.internal, ierr: + print ierr + sys.exit(1) + except error.exit, eerr: + sys.exit(2) + except KeyboardInterrupt: + if opts.find_arg('--stacktrace'): + print '}} dumping:', threading.active_count() + for t in threading.enumerate(): + print '}} ', t.name + print stacktraces() + log.notice('abort: user terminated') + sys.exit(1) + finally: + console.restore(stdtty) + sys.exit(0) + +if __name__ == "__main__": + run() diff --git a/tester/rt/version.py b/tester/rt/version.py new file mode 100644 index 0000000..7c82de3 --- /dev/null +++ b/tester/rt/version.py @@ -0,0 +1,48 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# Manage paths locally. The internally the path is in Unix or shell format and +# we convert to the native format when performing operations at the Python +# level. This allows macro expansion to work. +# + +major = 0 +minor = 2 +revision = 0 + +def str(): + return '%d.%d.%d'% (major, minor, revision) + +if __name__ == '__main__': + print 'major = %d' % (major) + print 'minor = %d' % (minor) + print 'revision = %d' % (revision) + print 'Version: %s' % (str()) diff --git a/tester/rtems-test b/tester/rtems-test new file mode 100755 index 0000000..53c81cd --- /dev/null +++ b/tester/rtems-test @@ -0,0 +1,42 @@ +#! /usr/bin/env python +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +import sys, os +base = os.path.dirname(os.path.abspath(sys.argv[0])) +parent = os.path.dirname(base) +sys.path = [base, parent] + sys.path + +try: + import rt.test + rt.test.run() +except ImportError: + print >> sys.stderr, "Incorrect RTEMS Tools installation" + sys.exit(1) diff --git a/tester/rtems/testing/bsps/mcf5235.mc b/tester/rtems/testing/bsps/mcf5235.mc new file mode 100644 index 0000000..f95fffb --- /dev/null +++ b/tester/rtems/testing/bsps/mcf5235.mc @@ -0,0 +1,63 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# All paths in defaults must be Unix format. Do not store any Windows format +# paths in the defaults. +# +# Every entry must describe the type of checking a host must pass. +# +# Records: +# key: type, attribute, value +# type : none, dir, exe, triplet +# attribute: none, required, optional +# value : 'single line', '''multi line''' +# + +# +# The Xilinx Zync ZC706 board connected via OpenOCD and a JTAG pod. The console +# is connected to a tty device. +# +[global] +bsp: none, none, 'mcf5235' +jobs: none, none, '1' + +[mcf5235] +mcf5235: none, none, '%{_rtscripts}/gdb.cfg' +mcf5235_arch: none, none, 'm68k' +bsp_tty_dev: none, none, '/dev/cuaU2' +bsp_tty_settings: none, none, 'B19200,~BRKINT,IGNBRK,IGNCR,~ICANON,~ISIG,~IEXTEN,~ECHO,~CLOCAL,VMIN=1,VTIME=2' +gdb_script: none, none, 'mcf5235_gdb_script' +mcf5235_gdb_script: none, none, '''target remote | m68k-bdm-gdbserver pipe 003-005 + thb *0xffe254c0 + continue + load + b bsp_reset + continue''' diff --git a/tester/rtems/testing/bsps/realview_pbx_a9_qemu.mc b/tester/rtems/testing/bsps/realview_pbx_a9_qemu.mc new file mode 100644 index 0000000..5a748c7 --- /dev/null +++ b/tester/rtems/testing/bsps/realview_pbx_a9_qemu.mc @@ -0,0 +1,53 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# All paths in defaults must be Unix format. Do not store any Windows format +# paths in the defaults. +# +# Every entry must describe the type of checking a host must pass. +# +# Records: +# key: type, attribute, value +# type : none, dir, exe, triplet +# attribute: none, required, optional +# value : 'single line', '''multi line''' +# + +# +# The Realview PBX A9 BSP. +# +[global] +bsp: none, none, 'realview_pbx_a9_qemu' + +[realview_pbx_a9_qemu] +realview_pbx_a9_qemu: none, none, '%{_rtscripts}/qemu.cfg' +realview_pbx_a9_qemu_arch: none, none, 'arm' +realview_pbx_a9_qemu_opts: none, none, '-no-reboot -serial /dev/null -serial mon:stdio -net none -nographic -M xilinx-zynq-a9 -m 256M' diff --git a/tester/rtems/testing/bsps/sis-run.mc b/tester/rtems/testing/bsps/sis-run.mc new file mode 100644 index 0000000..cbfcd27 --- /dev/null +++ b/tester/rtems/testing/bsps/sis-run.mc @@ -0,0 +1,54 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# All paths in defaults must be Unix format. Do not store any Windows format +# paths in the defaults. +# +# Every entry must describe the type of checking a host must pass. +# +# Records: +# key: type, attribute, value +# type : none, dir, exe, triplet +# attribute: none, required, optional +# value : 'single line', '''multi line''' +# + +# +# The SIS BSP +# +[global] +bsp: none, none, 'sis' + +[sis] +sis: none, none, '%{_rtscripts}/run.cfg' +sis_arch: none, none, 'sparc' +bsp_run_cmd: none, none, '%{rtems_tools}/%{bsp_arch}-rtems%{rtems_version}-run' +bsp_run_opts: none, none, '-a -nouartrx' diff --git a/tester/rtems/testing/bsps/sis.mc b/tester/rtems/testing/bsps/sis.mc new file mode 100644 index 0000000..ca84acd --- /dev/null +++ b/tester/rtems/testing/bsps/sis.mc @@ -0,0 +1,56 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# All paths in defaults must be Unix format. Do not store any Windows format +# paths in the defaults. +# +# Every entry must describe the type of checking a host must pass. +# +# Records: +# key: type, attribute, value +# type : none, dir, exe, triplet +# attribute: none, required, optional +# value : 'single line', '''multi line''' +# + +# +# The SIS BSP +# +[global] +bsp: none, none, 'sis' + +[sis] +sis: none, none, '%{_rtscripts}/gdb.cfg' +sis_arch: none, none, 'sparc' +gdb_script: none, none, 'sis_gdb_script' +sis_gdb_script: none, none, '''target sim + load + run''' diff --git a/tester/rtems/testing/bsps/xilinx_zynq_a9_qemu.mc b/tester/rtems/testing/bsps/xilinx_zynq_a9_qemu.mc new file mode 100644 index 0000000..22c2a88 --- /dev/null +++ b/tester/rtems/testing/bsps/xilinx_zynq_a9_qemu.mc @@ -0,0 +1,54 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# All paths in defaults must be Unix format. Do not store any Windows format +# paths in the defaults. +# +# Every entry must describe the type of checking a host must pass. +# +# Records: +# key: type, attribute, value +# type : none, dir, exe, triplet +# attribute: none, required, optional +# value : 'single line', '''multi line''' +# + +# +# The Xilinx Zynq A9 QEMU BSP +# +[global] +bsp: none, none, 'xilinx_zynq_a9_qemu' + +[xilinx_zynq_a9_qemu] +xilinx_zynq_a9_qemu: none, none, '%{_rtscripts}/run.cfg' +xilinx_zynq_a9_qemu_arch: none, none, 'arm' +bsp_run_cmd: none, none, 'qemu-system-arm' +bsp_run_opts: none, none, '-no-reboot -serial null -serial mon:stdio -nographic -net none -M xilinx-zynq-a9 -m 256M -kernel' diff --git a/tester/rtems/testing/bsps/xilinx_zynq_a9_qemu_smp.mc b/tester/rtems/testing/bsps/xilinx_zynq_a9_qemu_smp.mc new file mode 100644 index 0000000..bdd2ce7 --- /dev/null +++ b/tester/rtems/testing/bsps/xilinx_zynq_a9_qemu_smp.mc @@ -0,0 +1,55 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# All paths in defaults must be Unix format. Do not store any Windows format +# paths in the defaults. +# +# Every entry must describe the type of checking a host must pass. +# +# Records: +# key: type, attribute, value +# type : none, dir, exe, triplet +# attribute: none, required, optional +# value : 'single line', '''multi line''' +# + +# +# The Xilinx Zynq A9 QEMU BSP +# +[global] +bsp: none, none, 'xilinx_zynq_a9_qemu' + +[xilinx_zynq_a9_qemu] +xilinx_zynq_a9_qemu: none, none, '%{_rtscripts}/run.cfg' +xilinx_zynq_a9_qemu_arch: none, none, 'arm' +bsp_run_cmd: none, none, 'qemu-system-arm' +bsp_run_opts: none, none, '-no-reboot -serial null -serial mon:stdio -nographic -net none -M xilinx-zynq-a9 -m 256M -smp cpus=2 -kernel' +jobs: none, none, 'half' diff --git a/tester/rtems/testing/bsps/xilinx_zynq_zc706.mc b/tester/rtems/testing/bsps/xilinx_zynq_zc706.mc new file mode 100644 index 0000000..fc427ff --- /dev/null +++ b/tester/rtems/testing/bsps/xilinx_zynq_zc706.mc @@ -0,0 +1,65 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# All paths in defaults must be Unix format. Do not store any Windows format +# paths in the defaults. +# +# Every entry must describe the type of checking a host must pass. +# +# Records: +# key: type, attribute, value +# type : none, dir, exe, triplet +# attribute: none, required, optional +# value : 'single line', '''multi line''' +# + +# +# The Xilinx Zync ZC706 board connected via OpenOCD and a JTAG pod. The console +# is connected to a tty device. +# +[global] +bsp: none, none, 'xilinx_zynq_zc706' +jobs: none, none, '1' + +[xilinx_zynq_zc706] +xilinx_zynq_zc706: none, none, '%{_rtscripts}/gdb.cfg' +xilinx_zynq_zc706_arch: none, none, 'arm' +#bsp_tty_dev: none, none, '/dev/cuaU0' +bsp_tty_dev: none, none, '/dev/cu.SLAB_USBtoUART' +gdb_script: none, none, 'xilinx_zynq_zc706_gdb_script' +xilinx_zynq_zc706_gdb_script: none, none, '''target remote kaka:3333 +mon load_image /home/chris/development/si/work/hydra/boot/xilinx-zynq-fsbl/build/arm-rtems4.11-xilinx_zynq_zc706/hydra-fsbl.elf 0 elf + mon resume 0 + mon sleep 4000 + mon halt + load + b bsp_reset + continue''' diff --git a/tester/rtems/testing/console.cfg b/tester/rtems/testing/console.cfg new file mode 100644 index 0000000..c936e5c --- /dev/null +++ b/tester/rtems/testing/console.cfg @@ -0,0 +1,60 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# Consoles +# +# The rtems-test command can use a number of consoles. This file +# manages the BSP and user configuration of the console. +# + +# +# Backends can force the console to STDIO and igore any user settings. +# +%if %{defined console_stdio} + %if %{defined console_user_tty} + %warning command line TTY setting ignored + %endif + %console stdio +%else + # + # Console is TTY. + # + %if %{defined bsp_tty_dev} + %define tty_dev %{bsp_tty_dev} + %define tty_defaults B115200,~BRKINT,IGNBRK,IGNCR,~ICANON,~ISIG,~IEXTEN,~ECHO,CLOCAL,~CRTSCTS,VMIN=1,VTIME=2 + %if %{defined bsp_tty_settings} + %define tty_settings %{bsp_tty_settings} + %else + %define tty_settings %{tty_defaults} + %endif + %console tty %{tty_dev} %{tty_settings} + %endif +%endif diff --git a/tester/rtems/testing/defaults.mc b/tester/rtems/testing/defaults.mc new file mode 100644 index 0000000..bf220f3 --- /dev/null +++ b/tester/rtems/testing/defaults.mc @@ -0,0 +1,127 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# All paths in defaults must be Unix format. Do not store any Windows format +# paths in the defaults. +# +# Every entry must describe the type of checking a host must pass. +# +# Records: +# key: type, attribute, value +# type : none, dir, exe, triplet +# attribute: none, required, optional +# value : 'single line', '''multi line''' +# + +# +# Global defaults +# +[global] + +# Nothing +nil: none, none, '' + +# Paths +_topdir: dir, required, '%{_cwd}' +_docdir: dir, none, '%{_defaultdocdir}' +_tmppath: dir, none, '%{_topdir}/build/tmp' +_tmproot: dir, none, '%{_tmppath}/rt/%{_bset}' +_datadir: dir, none, '%{_prefix}/share' +_defaultdocdir: dir, none, '%{_prefix}/share/doc' +_exeext: none, none, '' +_exec_prefix: dir, none, '%{_prefix}' +_bindir: dir, none, '%{_exec_prefix}/bin' +_sbindir: dir, none, '%{_exec_prefix}/sbin' +_libexecdir: dir, none, '%{_exec_prefix}/libexec' +_datarootdir: dir, none, '%{_prefix}/share' +_datadir: dir, none, '%{_datarootdir}' +_sysconfdir: dir, none, '%{_prefix}/etc' +_sharedstatedir: dir, none, '%{_prefix}/com' +_localstatedir: dir, none, '%{prefix}/var' +_includedir: dir, none, '%{_prefix}/include' +_lib: dir, none, 'lib' +_libdir: dir, none, '%{_exec_prefix}/%{_lib}' +_libexecdir: dir, none, '%{_exec_prefix}/libexec' +_mandir: dir, none, '%{_datarootdir}/man' +_infodir: dir, none, '%{_datarootdir}/info' +_localedir: dir, none, '%{_datarootdir}/locale' +_localedir: dir, none, '%{_datadir}/locale' +_localstatedir: dir, none, '%{_prefix}/var' +_prefix: dir, none, '%{_usr}' +_usr: dir, none, '/usr/local' +_usrsrc: dir, none, '%{_usr}/src' +_var: dir, none, '/usr/local/var' +_varrun: dir, none, '%{_var}/run' + +# Defaults, override in platform specific modules. +__arch_install_post: exe, none, '%{nil}' +__bash: exe, optional, '/bin/bash' +__bzip2: exe, required, '/usr/bin/bzip2' +__cat: exe, required, '/bin/cat' +__chgrp: exe, required, '/usr/bin/chgrp' +__chmod: exe, required, '/bin/chmod' +__chown: exe, required, '/usr/sbin/chown' +__cp: exe, required, '/bin/cp' +__git: exe, required, '/usr/bin/git' +__grep: exe, required, '/usr/bin/grep' +__gzip: exe, required, '/usr/bin/gzip' +__id: exe, required, '/usr/bin/id' +__id_u: exe, none, '%{__id} -u' +__ln_s: exe, none, 'ln -s' +__make: exe, required, 'make' +__mkdir: exe, required, '/bin/mkdir' +__mkdir_p: exe, none, '/bin/mkdir -p' +__mv: exe, required, '/bin/mv' +__patch_bin: exe, required, '/usr/bin/patch' +__patch_opts: none, none, '%{nil}' +__patch: exe, none, '%{__patch_bin} %{__patch_opts}' +__svn: exe, optional, '/usr/bin/svn' +__rm: exe, required, '/bin/rm' +__rmfile: exe, none, '%{__rm} -f' +__rmdir: exe, none, '%{__rm} -rf' +__sed: exe, required, '/usr/bin/sed' +__sh: exe, required, '/bin/sh' +__tar: exe, required, '/usr/bin/tar' +__tar_extract: exe, none, '%{__tar} -xvvf' +__touch: exe, required, '/usr/bin/touch' +__unzip: exe, required, '/usr/bin/unzip' +__xz: exe, required, '/usr/bin/xz' + +# Default settings +_target: none, none, '%{nil}' + +# Paths +_rtbase: none, none, '%{_rtdir}' +_rttesting: none, none, '%{_rtbase}/rtems/testing' +_configdir: none, none, '%{_rtbase}/config:%{_rttesting}' + +# Include the testing macros. +%include %{_rttesting}/testing.mc diff --git a/tester/rtems/testing/gdb.cfg b/tester/rtems/testing/gdb.cfg new file mode 100644 index 0000000..b680dba --- /dev/null +++ b/tester/rtems/testing/gdb.cfg @@ -0,0 +1,60 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# Run +# +# Use a run command to run the executable. The run command is a GDB based +# simulator that is packaged as a single command that executes the program. +# + +%include %{_configdir}/base.cfg +%include %{_configdir}/checks.cfg + +# +# Console. +# +%include %{_configdir}/console.cfg + +# +# RTEMS version +# +%include %{_rtdir}/rtems/version.cfg + +# +# GDB executable +# +%define gdb_cmd %{rtems_tools}/%{bsp_arch}-rtems%{rtems_version}-gdb + +# +# GDB, pass the GDB command, the text executable and the macro label +# for the script. +# +%gdb %{gdb_cmd} %{test_executable} %{gdb_script} diff --git a/tester/rtems/testing/qemu.cfg b/tester/rtems/testing/qemu.cfg new file mode 100644 index 0000000..e15f058 --- /dev/null +++ b/tester/rtems/testing/qemu.cfg @@ -0,0 +1,60 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# QEMU +# +# Use a qemu command to run the executable in the qemu simulator. +# + +%include %{_configdir}/base.cfg +%include %{_configdir}/checks.cfg + +# +# Console. +# +%define console_stdio +%include %{_configdir}/console.cfg + +# +# RTEMS version +# +%include %{_rtdir}/rtems/version.cfg + +# +# Qemu executable +# +%define qemu_cmd qemu-system-%{bsp_arch} +%define qemu_opts %{bsp_opts} + +# +# Executable +# +%execute %{qemu_cmd} %{qemu_opts} -kernel %{test_executable} diff --git a/tester/rtems/testing/run.cfg b/tester/rtems/testing/run.cfg new file mode 100644 index 0000000..f7b21d7 --- /dev/null +++ b/tester/rtems/testing/run.cfg @@ -0,0 +1,70 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# Run +# +# Use a run command to run the executable. The run command is a GDB based +# simulator that is packaged as a single command that executes the program. +# + +%include %{_configdir}/base.cfg +%include %{_configdir}/checks.cfg + +# +# Console. +# +%define console_stdio +%include %{_configdir}/console.cfg + +# +# RTEMS version +# +%include %{_rtdir}/rtems/version.cfg + +# +# Run executable. +# +%ifn %{defined bsp_run_cmd} + %error No BSP run command provied. +%endif +%ifn %{defined bsp_run_opts} + %define bsp_run_opts %{nil} +%endif +%define run_cmd %{bsp_run_cmd} +%define run_opts %{bsp_run_opts} + +# +# Executable +# +%ifn %{defined test_executable_opts} + %define test_executable_opts %{nil} +%endif +%execute %{run_cmd} %{run_opts} %{test_executable} %{test_executable_opts} diff --git a/tester/rtems/testing/testing.mc b/tester/rtems/testing/testing.mc new file mode 100644 index 0000000..77f8419 --- /dev/null +++ b/tester/rtems/testing/testing.mc @@ -0,0 +1,57 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# All paths in defaults must be Unix format. Do not store any Windows format +# paths in the defaults. +# +# Every entry must describe the type of checking a host must pass. +# +# Records: +# key: type, attribute, value +# type : none, dir, exe, triplet +# attribute: none, required, optional +# value : 'single line', '''multi line''' +# + +# +# Global defaults +# +[global] + +# Paths +_rtbase: none, none, '%{_rtdir}' +_rtscripts: none, none, '%{_rtbase}/rtems/testing' + +# Defaults +timeout: none, none, '180' + +# Tests detected as invalid that are valid +invalid_tests: none, none, '''minimum.exe''' diff --git a/tester/rtems/version.cfg b/tester/rtems/version.cfg new file mode 100644 index 0000000..46f9939 --- /dev/null +++ b/tester/rtems/version.cfg @@ -0,0 +1,35 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# RTEMS Version +# + +%define rtems_version 4.11 |