diff options
author | Chris Johns <chrisj@rtems.org> | 2017-09-21 18:26:20 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2017-09-21 18:26:20 +1000 |
commit | 3a867a4919d84f6695c81105faafc06727fe56dd (patch) | |
tree | 2bc6c22e0ebe92a5024e91073cb2ea38df133ac0 /tester/rt/tftp.py | |
parent | Move the reraise logic into the tool kit. (diff) | |
download | rtems-tools-3a867a4919d84f6695c81105faafc06727fe56dd.tar.bz2 |
Add TFTP as a back end option for testing. Add telnet as a console option.
TFTP runs a local TFTP server on port 69 or another specified port and
serves each test for any requested file.
Telnet is now a console option.
Diffstat (limited to 'tester/rt/tftp.py')
-rw-r--r-- | tester/rt/tftp.py | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/tester/rt/tftp.py b/tester/rt/tftp.py new file mode 100644 index 0000000..ae0c4f3 --- /dev/null +++ b/tester/rt/tftp.py @@ -0,0 +1,208 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2017 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 TFTP Interface +# + +from __future__ import print_function + +import errno +import logging +import threading +import time +import sys + +from rtemstoolkit import error +from rtemstoolkit import reraise + +# +# Support to handle use in a package and as a unit test. +# If there is a better way to let us know. +# +try: + from . import tftpy +except (ValueError, SystemError): + import tftpy + +class tftp(object): + '''RTEMS Testing TFTP base.''' + + def __init__(self, bsp_arch, bsp, trace = False): + self.trace = trace + self.lock_trace = False + self.lock = threading.RLock() + self.bsp = bsp + self.bsp_arch = bsp_arch + self._init() + + def __del__(self): + self.kill() + + def _init(self): + self.output_length = None + self.console = None + self.server = None + self.port = 0 + self.exe = None + self.timeout = None + self.timer = None + self.running = False + self.finished = False + self.caught = None + + 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 _finished(self): + self.server = None + self.exe = None + + def _stop(self): + try: + if self.server: + self.server.stop(now = True) + except: + pass + + def _kill(self): + self._stop() + while self.running or not self.finished: + self._unlock('_kill') + time.sleep(0.1) + self._lock('_kill') + + def _timeout(self): + self._stop() + if self.timeout is not None: + self.timeout() + + def _exe_handle(self, req_file, raddress, rport): + self._lock('_exe_handle') + exe = self.exe + self.exe = None + self._unlock('_exe_handle') + if exe is not None: + if self.console: + self.console('tftp: %s' % (exe)) + return open(exe, "rb") + self._stop() + return None + + def _listener(self): + tftpy.log.setLevel(100) + try: + self.server = tftpy.TftpServer(tftproot = '.', + dyn_file_func = self._exe_handle) + except tftpy.TftpException as te: + raise error.general('tftp: %s' % (str(te))) + if self.server is not None: + try: + self.server.listen('0.0.0.0', self.port, 0.5) + except tftpy.TftpException as te: + raise error.general('tftp: %s' % (str(te))) + except IOError as ie: + if ie.errno == errno.EACCES: + raise error.general('tftp: permissions error: check tftp server port') + raise error.general('tftp: io error: %s' % (str(ie))) + + def _runner(self): + self._lock('_runner') + self.running = True + self._unlock('_runner') + caught = None + try: + self._listener() + except: + caught = sys.exc_info() + self._lock('_runner') + self._init() + self.running = False + self.finished = True + self.caught = caught + self._unlock('_runner') + + def open(self, executable, port, output_length, console, timeout): + self._lock('_open') + if self.exe is not None: + self._unlock('_open') + raise error.general('tftp: already running') + self._init() + self.output_length = output_length + self.console = console + self.port = port + self.exe = executable + self.timeout = timeout[1] + self.listener = threading.Thread(target = self._runner, + name = 'tftp-listener') + self.listener.start() + step = 1.0 + period = timeout[0] + output_len = self.output_length() + while not self.finished and period > 0: + current_length = self.output_length() + if output_length != current_length: + period = timeout[0] + output_length = current_length + if period < step: + period = 0 + else: + period -= step + self._unlock('_open') + time.sleep(step) + self._lock('_open') + if not self.finished and period == 0: + self._timeout() + caught = self.caught + self.caught = None + self._unlock('_open') + if caught is not None: + reraise.reraise(*caught) + + def kill(self): + self._lock('kill') + self._kill() + self._unlock('kill') + +if __name__ == "__main__": + import sys + if len(sys.argv) > 1: + executable = sys.argv[1] + else: + executable = None + t = tftp('arm', 'beagleboneblack') + t.open(executable) |