source: rtems-tools/tester/rt/config.py @ c04a849

4.104.115
Last change on this file since c04a849 was c04a849, checked in by Chris Johns <chrisj@…>, on 05/31/14 at 10:03:05

tester: Correctly handle contro-c.

Add support to kill running tests if the user presses control-c.

  • Property mode set to 100644
File size: 7.6 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2013-2014 Chris Johns (chrisj@rtems.org)
4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions are met:
10#
11# 1. Redistributions of source code must retain the above copyright notice,
12# this list of conditions and the following disclaimer.
13#
14# 2. Redistributions in binary form must reproduce the above copyright notice,
15# this list of conditions and the following disclaimer in the documentation
16# and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29#
30
31#
32# RTEMS Testing Config
33#
34
35import datetime
36import os
37import threading
38
39from rtemstoolkit import config
40from rtemstoolkit import error
41from rtemstoolkit import execute
42from rtemstoolkit import log
43from rtemstoolkit import path
44
45import console
46import gdb
47
48timeout = 15
49
50class file(config.file):
51    """RTEMS Testing configuration."""
52
53    _directives = ['%execute',
54                   '%gdb',
55                   '%console']
56
57    def __init__(self, report, name, opts, _directives = _directives):
58        super(file, self).__init__(name, opts, directives = _directives)
59        self.lock = threading.Lock()
60        self.realtime_trace = self.debug_trace('output')
61        self.process = None
62        self.console = None
63        self.output = None
64        self.report = report
65        self.name = name
66
67    def __del__(self):
68        if self.console:
69            del self.console
70        super(file, self).__del__()
71
72    def _lock(self):
73        self.lock.acquire()
74
75    def _unlock(self):
76        self.lock.release()
77
78    def _timeout(self):
79        self.capture('*** TIMEOUT TIMEOUT')
80
81    def _dir_console(self, data):
82        if self.console is not None:
83            raise error.general(self._name_line_msg('console already configured'))
84        if len(data) == 0:
85            raise error.general(self._name_line_msg('no console configuration provided'))
86        console_trace = trace = self.debug_trace('console')
87        if data[0] == 'stdio':
88            self.console = console.stdio(trace = console_trace)
89        elif data[0] == 'tty':
90            if len(data) < 2 or len(data) >3:
91                raise error.general(self._name_line_msg('no tty configuration provided'))
92            if len(data) == 3:
93                settings = data[2]
94            else:
95                settings = None
96            self.console = console.tty(data[1],
97                                       output = self.capture,
98                                       setup = settings,
99                                       trace = console_trace)
100        else:
101            raise error.general(self._name_line_msg('invalid console type'))
102
103    def _dir_execute(self, data, total, index, exe, bsp_arch, bsp):
104        self.process = execute.execute(output = self.capture)
105        if not self.in_error:
106            if self.console:
107                self.console.open()
108            self.capture_console('run: %s' % (' '.join(data)))
109            ec, proc = self.process.open(data,
110                                         timeout = (int(self.expand('%{timeout}')),
111                                                    self._timeout))
112            if ec > 0:
113                self._lock()
114                self._error('execute failed: %s: exit-code:%d' % (' '.join(data), ec))
115                self._unlock()
116            if self.console:
117                self.console.close()
118
119    def _dir_gdb(self, data, total, index, exe, bsp_arch, bsp):
120        if len(data) < 3 or len(data) > 4:
121            raise error.general('invalid %gdb arguments')
122        self.process = gdb.gdb(bsp_arch, bsp,
123                               trace = self.debug_trace('gdb'),
124                               mi_trace = self.debug_trace('gdb-mi'))
125        script = self.expand('%%{%s}' % data[2])
126        if script:
127            script = [l.strip() for l in script.splitlines()]
128        if not self.in_error:
129            if self.console:
130                self.console.open()
131            self.process.open(data[0], data[1],
132                              script = script,
133                              output = self.capture,
134                              gdb_console = self.capture_console,
135                              timeout = int(self.expand('%{timeout}')))
136            if self.console:
137                self.console.close()
138
139    def _directive_filter(self, results, directive, info, data):
140        if results[0] == 'directive':
141            _directive = results[1]
142            _data = results[2]
143            ds = []
144            if len(_data):
145                ds = [_data[0]]
146                if len(_data) > 1:
147                    ds += _data[1].split()
148            ds = self.expand(ds)
149
150            if _directive == '%console':
151                self._dir_console(ds)
152            else:
153                self._lock()
154                try:
155                    total = int(self.expand('%{test_total}'))
156                    index = int(self.expand('%{test_index}'))
157                    exe = self.expand('%{test_executable}')
158                    bsp_arch = self.expand('%{bsp_arch}')
159                    bsp = self.expand('%{bsp}')
160                    self.report.start(index, total, exe, exe, bsp_arch, bsp)
161                    self.output = []
162                finally:
163                    self._unlock()
164                if _directive == '%execute':
165                    self._dir_execute(ds, total, index, exe, bsp_arch, bsp)
166                elif _directive == '%gdb':
167                    self._dir_gdb(ds, total, index, exe, bsp_arch, bsp)
168                else:
169                    raise error.general(self._name_line_msg('invalid directive'))
170                self._lock()
171                try:
172                    self.report.end(exe, self.output)
173                    self.process = None
174                    self.output = None
175                finally:
176                    self._unlock()
177        return None, None, None
178
179    def _realtime_trace(self, text):
180        if self.realtime_trace:
181            for l in text:
182                print ' '.join(l)
183
184    def run(self):
185        self.load(self.name)
186
187    def capture(self, text):
188        text = [(']', l) for l in text.replace(chr(13), '').splitlines()]
189        self._lock()
190        if self.output is not None:
191            self._realtime_trace(text)
192            self.output += text
193        self._unlock()
194
195    def capture_console(self, text):
196        text = [('>', l) for l in text.replace(chr(13), '').splitlines()]
197        self._lock()
198        if self.output is not None:
199            self._realtime_trace(text)
200            self.output += text
201        self._unlock()
202
203    def debug_trace(self, flag):
204        dt = self.macros['debug_trace']
205        if dt:
206            if flag in dt.split(','):
207                return True
208        return False
209
210    def kill(self):
211        if self.process:
212            self.process.kill()
Note: See TracBrowser for help on using the repository browser.