source: rtems-tools/tester/rt/test.py @ a4c070c

4.11
Last change on this file since a4c070c was 7279748, checked in by Chris Johns <chrisj@…>, on 12/09/15 at 08:36:26

Add release versioning support.

Support a top level VERSION file that defines an RTEMS release.

Fix the install of the python modules including thertems-test.

Update the git python module to the RSB version. Fix the options to
not call clean and to call dirty.

Update the version python module.

Fix the rtld C++ support to the VERSION file and the top level waf
script.

  • Property mode set to 100644
File size: 12.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
31import copy
32import datetime
33import os
34import sys
35import threading
36import time
37
38from rtemstoolkit import error
39from rtemstoolkit import log
40from rtemstoolkit import path
41from rtemstoolkit import stacktraces
42from rtemstoolkit import version
43
44import bsps
45import config
46import console
47import options
48import report
49import fnmatch
50
51class test(object):
52    def __init__(self, index, total, report, executable, rtems_tools, bsp, bsp_config, opts):
53        self.index = index
54        self.total = total
55        self.report = report
56        self.bsp = bsp
57        self.bsp_config = bsp_config
58        self.opts = copy.copy(opts)
59        self.opts.defaults['test_index'] = str(index)
60        self.opts.defaults['test_total'] = str(total)
61        self.opts.defaults['bsp'] = bsp
62        self.opts.defaults['bsp_arch'] = '%%{%s_arch}' % (bsp)
63        self.opts.defaults['bsp_opts'] = '%%{%s_opts}' % (bsp)
64        if not path.isfile(executable):
65            raise error.general('cannot find executable: %s' % (executable))
66        self.opts.defaults['test_executable'] = executable
67        if rtems_tools:
68            rtems_tools_bin = path.join(self.opts.defaults.expand(rtems_tools), 'bin')
69            if not path.isdir(rtems_tools_bin):
70                raise error.general('cannot find RTEMS tools path: %s' % (rtems_tools_bin))
71            self.opts.defaults['rtems_tools'] = rtems_tools_bin
72        self.config = config.file(self.report, self.bsp_config, self.opts)
73
74    def run(self):
75        if self.config:
76            self.config.run()
77
78    def kill(self):
79        if self.config:
80            self.config.kill()
81
82class test_run(object):
83    def __init__(self, index, total, report, executable, rtems_tools, bsp, bsp_config, opts):
84        self.test = None
85        self.result = None
86        self.start_time = None
87        self.end_time = None
88        self.index = copy.copy(index)
89        self.total = total
90        self.report = report
91        self.executable = copy.copy(executable)
92        self.rtems_tools = rtems_tools
93        self.bsp = bsp
94        self.bsp_config = bsp_config
95        self.opts = opts
96
97    def runner(self):
98        self.start_time = datetime.datetime.now()
99        try:
100            self.test = test(self.index, self.total, self.report,
101                             self.executable, self.rtems_tools,
102                             self.bsp, self.bsp_config,
103                             self.opts)
104            self.test.run()
105        except KeyboardInterrupt:
106            pass
107        except:
108            self.result = sys.exc_info()
109        self.end_time = datetime.datetime.now()
110
111    def run(self):
112        self.thread = threading.Thread(target = self.runner,
113                                       name = 'test[%s]' % path.basename(self.executable))
114        self.thread.start()
115
116    def is_alive(self):
117        return self.thread and self.thread.is_alive()
118
119    def reraise(self):
120        if self.result is not None:
121            raise self.result[0], self.result[1], self.result[2]
122
123    def kill(self):
124        if self.test:
125            self.test.kill()
126
127def find_executables(paths, glob):
128    executables = []
129    for p in paths:
130        if path.isfile(p):
131            executables += [p]
132        elif path.isdir(p):
133            for root, dirs, files in os.walk(p, followlinks = True):
134                for f in files:
135                    if fnmatch.fnmatch(f.lower(), glob):
136                        executables += [path.join(root, f)]
137    return sorted(executables)
138
139def report_finished(reports, report_mode, reporting, finished, job_trace):
140    processing = True
141    while processing:
142        processing = False
143        reported = []
144        for tst in finished:
145            if tst not in reported and \
146                    (reporting < 0 or tst.index == reporting):
147                if job_trace:
148                    log.notice('}} %*d: %s: %s (%d)' % (len(str(tst.total)), tst.index,
149                                                        path.basename(tst.executable),
150                                                        'reporting',
151                                                        reporting))
152                processing = True
153                reports.log(tst.executable, report_mode)
154                reported += [tst]
155                reporting += 1
156        finished[:] = [t for t in finished if t not in reported]
157        if len(reported):
158            del reported[:]
159            if job_trace:
160                print '}} threading:', threading.active_count()
161                for t in threading.enumerate():
162                    print '}} ', t.name
163    return reporting
164
165def _job_trace(tst, msg, total, exe, active, reporting):
166    s = ''
167    for a in active:
168        s += ' %d:%s' % (a.index, path.basename(a.executable))
169    log.notice('}} %*d: %s: %s (%d %d %d%s)' % (len(str(tst.total)), tst.index,
170                                                path.basename(tst.executable),
171                                                msg,
172                                                reporting, total, exe, s))
173
174def list_bsps(opts):
175    path_ = opts.defaults.expand('%%{_configdir}/bsps/*.mc')
176    bsps = path.collect_files(path_)
177    log.notice(' BSP List:')
178    for bsp in bsps:
179        log.notice('  %s' % (path.basename(bsp[:-3])))
180    raise error.exit()
181
182def killall(tests):
183    for test in tests:
184        test.kill()
185
186def run(command_path = None):
187    import sys
188    tests = []
189    stdtty = console.save()
190    opts = None
191    default_exefilter = '*.exe'
192    try:
193        optargs = { '--rtems-tools': 'The path to the RTEMS tools',
194                    '--rtems-bsp':   'The RTEMS BSP to run the test on',
195                    '--report-mode': 'Reporting modes, failures (default),all,none',
196                    '--list-bsps':   'List the supported BSPs',
197                    '--debug-trace': 'Debug trace based on specific flags',
198                    '--filter':      'Glob that executables must match to run (default: ' +
199                              default_exefilter + ')',
200                    '--stacktrace':  'Dump a stack trace on a user termination (^C)' }
201        opts = options.load(sys.argv,
202                            optargs = optargs,
203                            command_path = command_path)
204        log.notice('RTEMS Testing - Tester, %s' % (version.str()))
205        if opts.find_arg('--list-bsps'):
206            bsps.list(opts)
207        exe_filter = opts.find_arg('--filter')
208        if exe_filter:
209            exe_filter = exe_filter[1]
210        else:
211            exe_filter = default_exefilter
212        opts.log_info()
213        debug_trace = opts.find_arg('--debug-trace')
214        if debug_trace:
215            debug_trace = debug_trace[1]
216        else:
217            debug_trace = ''
218        opts.defaults['debug_trace'] = debug_trace
219        job_trace = 'jobs' in debug_trace.split(',')
220        rtems_tools = opts.find_arg('--rtems-tools')
221        if rtems_tools:
222            if len(rtems_tools) != 2:
223                raise error.general('invalid RTEMS tools option')
224            rtems_tools = rtems_tools[1]
225        else:
226            rtems_tools = '%{_prefix}'
227        bsp = opts.find_arg('--rtems-bsp')
228        if bsp is None or len(bsp) != 2:
229            raise error.general('RTEMS BSP not provided or invalid option')
230        opts.defaults.load('%%{_configdir}/bsps/%s.mc' % (bsp[1]))
231        bsp = opts.defaults.get('%{bsp}')
232        if not bsp:
233            raise error.general('BSP definition (%{bsp}) not found in the global map')
234        bsp = bsp[2]
235        if not opts.defaults.set_read_map(bsp):
236            raise error.general('no BSP map found')
237        bsp_script = opts.defaults.get(bsp)
238        if not bsp_script:
239            raise error.general('BSP script not found: %s' % (bsp))
240        bsp_config = opts.defaults.expand(opts.defaults[bsp])
241        report_mode = opts.find_arg('--report-mode')
242        if report_mode:
243            if report_mode[1] != 'failures' and \
244                    report_mode[1] != 'all' and \
245                    report_mode[1] != 'none':
246                raise error.general('invalid report mode')
247            report_mode = report_mode[1]
248        else:
249            report_mode = 'failures'
250        executables = find_executables(opts.params(), exe_filter)
251        if len(executables) == 0:
252            raise error.general('no executables supplied')
253        start_time = datetime.datetime.now()
254        total = len(executables)
255        reports = report.report(total)
256        invalid_tests = opts.defaults['invalid_tests']
257        if invalid_tests:
258            reports.set_invalid_tests([l.strip() for l in invalid_tests.splitlines()])
259        reporting = 1
260        jobs = int(opts.jobs(opts.defaults['_ncpus']))
261        exe = 0
262        finished = []
263        if jobs > len(executables):
264            jobs = len(executables)
265        while exe < total or len(tests) > 0:
266            if exe < total and len(tests) < jobs:
267                tst = test_run(exe + 1, total, reports,
268                               executables[exe],
269                               rtems_tools, bsp, bsp_config,
270                               opts)
271                exe += 1
272                tests += [tst]
273                if job_trace:
274                    _job_trace(tst, 'create',
275                               total, exe, tests, reporting)
276                tst.run()
277            else:
278                dead = [t for t in tests if not t.is_alive()]
279                tests[:] = [t for t in tests if t not in dead]
280                for tst in dead:
281                    if job_trace:
282                        _job_trace(tst, 'dead',
283                                   total, exe, tests, reporting)
284                    finished += [tst]
285                    tst.reraise()
286                del dead
287                if len(tests) >= jobs or exe >= total:
288                    time.sleep(0.250)
289                if len(finished):
290                    reporting = report_finished(reports,
291                                                report_mode,
292                                                reporting,
293                                                finished,
294                                                job_trace)
295        finished_time = datetime.datetime.now()
296        reporting = report_finished(reports, report_mode,
297                                    reporting, finished, job_trace)
298        if reporting < total:
299            log.warning('finished jobs does match: %d' % (reporting))
300            report_finished(reports, report_mode, -1, finished, job_trace)
301        reports.summary()
302        end_time = datetime.datetime.now()
303        log.notice('Average test time: %s' % (str((end_time - start_time) / total)))
304        log.notice('Testing time     : %s' % (str(end_time - start_time)))
305    except error.general, gerr:
306        print gerr
307        sys.exit(1)
308    except error.internal, ierr:
309        print ierr
310        sys.exit(1)
311    except error.exit, eerr:
312        sys.exit(2)
313    except KeyboardInterrupt:
314        if opts is not None and opts.find_arg('--stacktrace'):
315            print '}} dumping:', threading.active_count()
316            for t in threading.enumerate():
317                print '}} ', t.name
318            print stacktraces.trace()
319        log.notice('abort: user terminated')
320        killall(tests)
321        sys.exit(1)
322    finally:
323        console.restore(stdtty)
324    sys.exit(0)
325
326if __name__ == "__main__":
327    run()
Note: See TracBrowser for help on using the repository browser.