def run(args, command_path=None): import sys tests = [] stdtty = console.save() opts = None default_exefilter = '*.exe' try: optargs = { '--rtems-tools': 'The path to the RTEMS tools', '--rtems-bsp': 'The RTEMS BSP to run the test on', '--user-config': 'Path to your local user configuration INI file', '--report-path': 'Report output base path (file extension will be added)', '--report-format': 'Formats in which to report test results in addition to txt: json', '--log-mode': 'Reporting modes, failures (default),all,none', '--list-bsps': 'List the supported BSPs', '--debug-trace': 'Debug trace based on specific flags (console,gdb,output,cov)', '--filter': 'Glob that executables must match to run (default: ' + default_exefilter + ')', '--stacktrace': 'Dump a stack trace on a user termination (^C)', '--coverage': 'Perform coverage analysis of test executables.' } mailer.append_options(optargs) opts = options.load(args, optargs=optargs, command_path=command_path) mail = None output = None if opts.find_arg('--mail'): mail = mailer.mail(opts) # Request these now to generate any errors. from_addr = mail.from_address() smtp_host = mail.smtp_host() to_addr = opts.find_arg('--mail-to') if to_addr: to_addr = to_addr[1] else: to_addr = '*****@*****.**' output = log_capture() report_location = opts.find_arg('--report-path') if report_location is not None: report_location = report_location[1] report_formats = opts.find_arg('--report-format') if report_formats is not None: if len(report_formats) != 2: raise error.general('invalid RTEMS report formats option') report_formats = report_formats[1].split(',') check_report_formats(report_formats, report_location) else: report_formats = [] log.notice('RTEMS Testing - Tester, %s' % (version.string())) if opts.find_arg('--list-bsps'): bsps.list(opts) exe_filter = opts.find_arg('--filter') if exe_filter: exe_filter = exe_filter[1] else: exe_filter = default_exefilter opts.log_info() log.output('Host: ' + host.label(mode='all')) executables = find_executables(opts.params(), exe_filter) debug_trace = opts.find_arg('--debug-trace') if debug_trace: if len(debug_trace) != 1: debug_trace = debug_trace[1] else: raise error.general( 'no debug flags, can be: console,gdb,output,cov') else: debug_trace = '' opts.defaults['exe_trace'] = debug_trace job_trace = 'jobs' in debug_trace.split(',') rtems_tools = opts.find_arg('--rtems-tools') if rtems_tools is not None: if len(rtems_tools) != 2: raise error.general('invalid RTEMS tools option') rtems_tools = rtems_tools[1] bsp = opts.find_arg('--rtems-bsp') if bsp is None or len(bsp) != 2: raise error.general('RTEMS BSP not provided or an invalid option') bsp = config.load(bsp[1], opts) bsp_config = opts.defaults.expand(opts.defaults['tester']) coverage_enabled = opts.find_arg('--coverage') if coverage_enabled: cov_trace = 'cov' in debug_trace.split(',') if len(coverage_enabled) == 2: coverage_runner = coverage.coverage_run( opts.defaults, executables, rtems_tools, symbol_set=coverage_enabled[1], trace=cov_trace) else: coverage_runner = coverage.coverage_run(opts.defaults, executables, rtems_tools, trace=cov_trace) log_mode = opts.find_arg('--log-mode') if log_mode: if log_mode[1] != 'failures' and \ log_mode[1] != 'all' and \ log_mode[1] != 'none': raise error.general('invalid report mode') log_mode = log_mode[1] else: log_mode = 'failures' if len(executables) == 0: raise error.general('no executables supplied') start_time = datetime.datetime.now() total = len(executables) reports = report.report(total) reporting = 1 jobs = int(opts.jobs(opts.defaults['_ncpus'])) exe = 0 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, log_mode, reporting, finished, job_trace) finished_time = datetime.datetime.now() reporting = report_finished(reports, log_mode, reporting, finished, job_trace) if reporting < total: log.warning('finished jobs does match: %d' % (reporting)) report_finished(reports, log_mode, -1, finished, job_trace) reports.summary() end_time = datetime.datetime.now() average_time = 'Average test time: %s' % (str( (end_time - start_time) / total)) total_time = 'Testing time : %s' % (str(end_time - start_time)) log.notice(average_time) log.notice(total_time) for report_format in report_formats: report_formatters[report_format]( args, reports, start_time, end_time, total, '.'.join([report_location, report_format])) if mail is not None and output is not None: m_arch = opts.defaults.expand('%{arch}') m_bsp = opts.defaults.expand('%{bsp}') build = ' %s:' % (reports.get_config('build', not_found='')) subject = '[rtems-test] %s/%s:%s %s' % ( m_arch, m_bsp, build, reports.score_card('short')) np = 'Not present in test' ver = reports.get_config('version', not_found=np) build = reports.get_config('build', not_found=np) tools = reports.get_config('tools', not_found=np) body = [ total_time, average_time, '', 'Host', '====', host.label(mode='all'), '', 'Configuration', '=============', 'Version: %s' % (ver), 'Build : %s' % (build), 'Tools : %s' % (tools), '', 'Summary', '=======', '', reports.score_card(), '', reports.failures(), 'Log', '===', '' ] + output.get() mail.send(to_addr, subject, os.linesep.join(body)) if coverage_enabled: coverage_runner.run() except error.general as gerr: print(gerr) sys.exit(1) except error.internal as ierr: print(ierr) sys.exit(1) except error.exit: sys.exit(2) except KeyboardInterrupt: if opts is not None and opts.find_arg('--stacktrace'): print('}} dumping:', threading.active_count()) for t in threading.enumerate(): print('}} ', t.name) print(stacktraces.trace()) log.notice('abort: user terminated') killall(tests) sys.exit(1) finally: console.restore(stdtty) sys.exit(0)
def run(args): b = None ec = 0 try: rtems.clean_windows_path() start = _now() prefix = '/opt/rtems/%s' % (rtems_version()) tools = prefix build_dir = 'bsp-builds' logf = 'bsp-build-%s.txt' % (_now().strftime('%Y%m%d-%H%M%S')) config_file = rtems.bsp_configuration_file(prog=args[0]) description = 'RTEMS BSP Builder is a BSP build tester. It builds BSPs ' description += 'in various ways to test build regressions in the kernel. You ' description += 'can build based on tier, architecture, or BSP. You can control ' description += 'the profile of build with various build configuration settings.' argsp = argparse.ArgumentParser(prog='rtems-bsp-builder', description=description) argsp.add_argument('--prefix', help='Prefix to build the BSP.', type=str) argsp.add_argument('--rtems-tools', help='The RTEMS tools directory.', type=str) argsp.add_argument('--rtems', help='The RTEMS source tree.', type=str) argsp.add_argument('--build-path', help='Path to build in.', type=str) argsp.add_argument('--log', help='Log file.', type=str) argsp.add_argument('--config-report', help='Report the configuration.', type=str, default=None, choices=['all', 'profiles', 'builds', 'archs']) argsp.add_argument('--warnings-report', help='Report the warnings to a file.', type=str, default=None) argsp.add_argument('--failures-report', help='Report the failures to a file.', type=str, default=None) argsp.add_argument('--stop-on-error', help='Stop on an error.', action='store_true') argsp.add_argument('--no-clean', help='Do not clean the build output.', action='store_true') argsp.add_argument( '--profiles', help='Build the listed profiles (profile,profile,..).', type=str, default='tier-1') argsp.add_argument('--arch', help='Build the architectures (arch,arch,..).', type=str) argsp.add_argument('--bsp', help='Build the BSPs (arch/bsp,arch/bsp,..).', type=str) argsp.add_argument('--build', help='Build name to build (see --config-report).', type=str, default='all') argsp.add_argument('--jobs', help='Number of jobs to run.', type=str, default='1/%d' % (host.cpus())) argsp.add_argument('--dry-run', help='Do not run the actual builds.', action='store_true') mailer.add_arguments(argsp) opts = argsp.parse_args(args[1:]) mail = None if opts.mail: mail = mailer.mail(opts) # Request these now to generate any errors. from_addr = mail.from_address() smtp_host = mail.smtp_host() if 'mail_to' in opts and opts.mail_to is not None: to_addr = opts.mail_to else: to_addr = '*****@*****.**' if opts.log is not None: logf = opts.log log.default = log.log([logf]) log.notice(title()) log.output(command_line()) if mail: log.notice('Mail: from:%s to:%s smtp:%s' % (from_addr, to_addr, smtp_host)) config = rtems.configuration() config.load(config_file, opts.build) if opts.config_report: log.notice('Configuration Report: %s' % (opts.config_report)) c_profiles = False c_builds = False c_archs = False if opts.config_report == 'all': c_profiles = True c_builds = True c_archs = True elif opts.config_report == 'profiles': c_profiles = True elif opts.config_report == 'builds': c_builds = True elif opts.config_report == 'archs': c_archs = True log.notice(config.report(c_profiles, c_builds, c_archs)) sys.exit(0) if opts.rtems is None: raise error.general('No RTEMS source provided on the command line') if opts.prefix is not None: prefix = path.shell(opts.prefix) if opts.rtems_tools is not None: tools = path.shell(opts.rtems_tools) if opts.build_path is not None: build_dir = path.shell(opts.build_path) options = { 'stop-on-error': opts.stop_on_error, 'no-clean': opts.no_clean, 'dry-run': opts.dry_run, 'jobs': opts.jobs, 'warnings-report': opts.warnings_report, 'failures-report': opts.failures_report } b = builder(config, rtems_version(), prefix, tools, path.shell(opts.rtems), build_dir, options) profiles = comma_split(opts.profiles) archs = comma_split(opts.arch) bsps = comma_split(opts.bsp) # # The default is build a profile. # if bsps is not None: if archs is not None: raise error.general('--arch supplied with --bsp;' \ ' use --bsp=arch/bsp,arch/bsp,..') what = 'BSPs: %s' % (' '.join(bsps)) b.build_bsps(bsps) elif archs is not None: what = 'Archs: %s' % (' '.join(archs)) b.build_archs(archs) else: what = 'Profile(s): %s' % (' '.join(profiles)) b.build_profiles(profiles) end = _now() # # Email the results of the build. # if mail is not None: subject = '[rtems-bsp-builder] %s: %s' % (str(start).split('.')[0], what) t = title() body = t + os.linesep body += '=' * len(t) + os.linesep body += os.linesep body += 'Host: %s' % (os.uname()[3]) + os.linesep body += os.linesep body += command_line() body += os.linesep body += 'Total Time : %s for %d completed job(s)' % \ (str(b.duration), b.jobs_completed) body += os.linesep body += 'Average BSP Build Time: %s' % (str(b.average)) body += os.linesep + os.linesep body += 'Builds' + os.linesep body += '======' + os.linesep body += os.linesep.join([' ' + cb for cb in config.builds()]) body += os.linesep + os.linesep body += 'Failures Report' + os.linesep body += '===============' + os.linesep body += b.results.failures_report() body += os.linesep body += 'Warnings Report' + os.linesep body += '===============' + os.linesep body += b.results.warnings_report(summary=True) mail.send(to_addr, subject, body) except error.general as gerr: print(gerr) print('BSP Build FAILED', file=sys.stderr) ec = 1 except error.internal as ierr: print(ierr) print('BSP Build FAILED', file=sys.stderr) ec = 1 except error.exit as eerr: pass except KeyboardInterrupt: log.notice('abort: user terminated') ec = 1 if b is not None: b.results.report() sys.exit(ec)