From 59880c0933e2869c5359cadc227223562a20f5a5 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Mon, 20 Sep 2021 21:33:08 -1000 Subject: tester/wait: Add a wait directive to the tester - Lets you test with stand alone TFTP or other services --- tester/rt/config.py | 27 +++++++- tester/rt/wait.py | 154 ++++++++++++++++++++++++++++++++++++++++++ tester/rtems/testing/wait.cfg | 54 +++++++++++++++ 3 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 tester/rt/wait.py create mode 100644 tester/rtems/testing/wait.cfg (limited to 'tester') diff --git a/tester/rt/config.py b/tester/rt/config.py index 61e8f0d..a7b9ee3 100644 --- a/tester/rt/config.py +++ b/tester/rt/config.py @@ -52,6 +52,7 @@ import tester.rt.console import tester.rt.exe import tester.rt.gdb import tester.rt.tftp +import tester.rt.wait timeout = 15 @@ -61,6 +62,7 @@ class file(config.file): _directives = ['%execute', '%gdb', '%tftp', + '%wait', '%console'] def __init__(self, index, total, report, name, opts, @@ -217,8 +219,8 @@ class file(config.file): if data[0] == 'stdio': self.console = tester.rt.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) < 2 or len(data) > 3: + raise error.general(self._name_line_msg('invalid tty configuration provided')) if len(data) == 3: settings = data[2] else: @@ -296,6 +298,25 @@ class file(config.file): if self.console: self.console.close() + def _dir_wait(self, data, total, index, exe, bsp_arch, bsp): + if len(data) != 0: + raise error.general('%wait has no arguments') + self.kill_on_end = True + if not self.opts.dry_run(): + self.process = tester.rt.wait.wait(bsp_arch, bsp, + trace = self.exe_trace('wait')) + if not self.in_error: + if self.console: + self.console.open() + self.process.open(output_length = self._output_length, + console = self.capture_console, + timeout = (int(self.expand('%{timeout}')), + int(self.expand('%{max_test_period}')), + self._timeout, + self._test_too_long)) + if self.console: + self.console.close() + def _directive_filter(self, results, directive, info, data): if results[0] == 'directive': _directive = results[1] @@ -332,6 +353,8 @@ class file(config.file): self._dir_gdb(ds, total, index, fexe, bsp_arch, bsp) elif _directive == '%tftp': self._dir_tftp(ds, total, index, fexe, bsp_arch, bsp) + elif _directive == '%wait': + self._dir_wait(ds, total, index, fexe, bsp_arch, bsp) else: raise error.general(self._name_line_msg('invalid directive')) self._lock() diff --git a/tester/rt/wait.py b/tester/rt/wait.py new file mode 100644 index 0000000..a42e5e5 --- /dev/null +++ b/tester/rt/wait.py @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: BSD-2-Clause +'''Wait test target.''' + +# Copyright (C) 2013-2021 Chris Johns (chrisj@rtems.org) +# +# 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 OWNER 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. + +from __future__ import print_function + +import datetime +import os +import threading +import time + + +class wait(object): + '''RTEMS Testing WAIT base.''' + + # pylint: disable=useless-object-inheritance + # pylint: disable=too-many-instance-attributes + + def __init__(self, bsp_arch, bsp, trace=False): + self.trace = trace + self.lock_trace = False + self.lock_locked = None + self.lock = threading.RLock() + self.bsp = bsp + self.bsp_arch = bsp_arch + self._init() + + def _init(self): + self.output_length = None + self.console = None + self.server = None + self.timeout = None + self.test_too_long = None + self.timer = None + self.waiting = False + self.seconds = 0 + + def _lock(self, msg): + if self.lock_trace: + print('|[ LOCK:%s ]|' % (msg)) + self.lock_locked = datetime.datetime.now() + self.lock.acquire() + + def _unlock(self, msg): + if self.lock_trace: + period = datetime.datetime.now() - self.lock_locked + print('|] UNLOCK:%s [| : %s' % (msg, period)) + self.lock.release() + + def _trace(self, text): + if log.tracing: + log.trace('] wait: ' + text) + + def _console(self, text): + if self.console: + self.console(text) + + def _kill(self): + self._lock('_kill') + self._console('wait: kill') + self.waiting = False + self._unlock('_kill') + + def _timeout(self): + self._kill() + if self.timeout is not None: + self.timeout() + + def _test_too_long(self): + self._kill() + if self.test_too_long is not None: + self.test_too_long() + + def _monitor(self, timeout): + output_length = self.output_length + period = timeout[0] + seconds = timeout[1] + self._console('wait: start: period=%d seconds=%d' % (period, seconds)) + step = 0.5 + period *= step + seconds *= step + self.waiting = True + while self.waiting and period > 0 and seconds > 0: + self._unlock('_monitor') + current_length = self.output_length() + if output_length != current_length: + period = timeout[0] * step + output_length = current_length + if seconds < step: + seconds = 0 + else: + seconds -= step + if period < step: + step = period + period = 0 + else: + period -= step + time.sleep(step) + self._lock('_monitor') + if self.waiting: + if period == 0: + self._timeout() + elif seconds == 0: + self._test_too_long() + self._console('wait: finished: period=%d seconds=%d' % (period, seconds)) + + def open(self, output_length, console, timeout): + '''Start to wait''' + # pylint: disable=too-many-arguments + self._lock('_open') + self._init() + self.output_length = output_length + self.console = console + self.timeout = timeout[2] + self.test_too_long = timeout[3] + self._monitor(timeout) + + def kill(self): + '''Kill the test run.''' + self._kill() + + def target_restart(self, started): + pass + + def target_reset(self, started): + pass + + def target_start(self): + pass + + def target_end(self): + pass diff --git a/tester/rtems/testing/wait.cfg b/tester/rtems/testing/wait.cfg new file mode 100644 index 0000000..4eade4f --- /dev/null +++ b/tester/rtems/testing/wait.cfg @@ -0,0 +1,54 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2021 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. +# + +# +# Wait +# +# Use a wait command to wait the timeout period. The wait will be stopped +# when the test finishes. +# + +%include %{_configdir}/base.cfg +%include %{_configdir}/checks.cfg + +# +# Console. +# +%include %{_configdir}/console.cfg + +# +# RTEMS version +# +%include %{_rtdir}/rtems/version.cfg + +# +# Wait +# +%wait -- cgit v1.2.3