| # -*- mode:python -*- | |
| # | |
| # Copyright (c) 2016 ARM Limited | |
| # All rights reserved | |
| # | |
| # The license below extends only to copyright in the software and shall | |
| # not be construed as granting a license to any other intellectual | |
| # property including but not limited to intellectual property relating | |
| # to a hardware implementation of the functionality of the software | |
| # licensed hereunder. You may use the software subject to the license | |
| # terms below provided that you ensure that this notice is replicated | |
| # unmodified and in its entirety in all distributions of the software, | |
| # modified or unmodified, in source code or in binary form. | |
| # | |
| # Copyright (c) 2004-2006 The Regents of The University of Michigan | |
| # All rights reserved. | |
| # | |
| # Redistribution and use in source and binary forms, with or without | |
| # modification, are permitted provided that the following conditions are | |
| # met: redistributions of source code must retain the above copyright | |
| # notice, this list of conditions and the following disclaimer; | |
| # 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; | |
| # neither the name of the copyright holders nor the names of its | |
| # contributors may be used to endorse or promote products derived from | |
| # this software without specific prior written permission. | |
| # | |
| # 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. | |
| # | |
| # Authors: Steve Reinhardt | |
| # Kevin Lim | |
| # Andreas Sandberg | |
| from __future__ import print_function | |
| from SCons.Script.SConscript import SConsEnvironment | |
| import os | |
| import pickle | |
| import sys | |
| sys.path.insert(0, Dir(".").srcnode().abspath) | |
| import testing.tests as tests | |
| import testing.results as results | |
| from gem5_scons.util import get_termcap | |
| Import('env') | |
| # get the termcap from the environment | |
| termcap = get_termcap() | |
| # Dict that accumulates lists of tests by category (quick, medium, long) | |
| env.Tests = {} | |
| gpu_isa = env['TARGET_GPU_ISA'] if env['BUILD_GPU'] else None | |
| for cat in tests.all_categories: | |
| env.Tests[cat] = tuple( | |
| tests.get_tests(env["TARGET_ISA"], | |
| categories=(cat, ), | |
| ruby_protocol=env["PROTOCOL"], | |
| gpu_isa=gpu_isa)) | |
| def color_message(color, msg): | |
| return color + msg + termcap.Normal | |
| def run_test(target, source, env): | |
| """Run a test and produce results as a pickle file. | |
| Targets are as follows: | |
| target[0] : Pickle file | |
| Sources are: | |
| source[0] : gem5 binary | |
| source[1] : tests/run.py script | |
| source[2:] : reference files | |
| """ | |
| tgt_dir = os.path.dirname(str(target[0])) | |
| config = tests.ClassicConfig(*tgt_dir.split('/')[-6:]) | |
| test = tests.ClassicTest(source[0].abspath, tgt_dir, config, | |
| timeout=5*60*60, | |
| skip_diff_out=True) | |
| for ref in test.ref_files(): | |
| out_file = os.path.join(tgt_dir, ref) | |
| if os.path.exists(out_file): | |
| env.Execute(Delete(out_file)) | |
| with open(target[0].abspath, "wb") as fout: | |
| formatter = results.Pickle(fout=fout) | |
| formatter.dump_suites([ test.run() ]) | |
| return 0 | |
| def run_test_string(target, source, env): | |
| return env.subst("Running test in ${TARGETS[0].dir}.", | |
| target=target, source=source) | |
| testAction = env.Action(run_test, run_test_string) | |
| def print_test(target, source, env): | |
| """Run a test and produce results as a pickle file. | |
| Targets are as follows: | |
| target[*] : Dummy targets | |
| Sources are: | |
| source[0] : Pickle file | |
| """ | |
| with open(source[0].abspath, "rb") as fin: | |
| result = pickle.load(fin) | |
| assert len(result) == 1 | |
| result = result[0] | |
| formatter = None | |
| if result.skipped(): | |
| status = color_message(termcap.Cyan, "skipped.") | |
| elif result.changed(): | |
| status = color_message(termcap.Yellow, "CHANGED!") | |
| formatter = results.Text() | |
| elif result: | |
| status = color_message(termcap.Green, "passed.") | |
| else: | |
| status = color_message(termcap.Red, "FAILED!") | |
| formatter = results.Text() | |
| if formatter: | |
| formatter.dump_suites([result]) | |
| print("***** %s: %s" % (source[0].dir, status)) | |
| return 0 | |
| printAction = env.Action(print_test, strfunction=None) | |
| def update_test(target, source, env): | |
| """Update test reference data | |
| Targets are as follows: | |
| target[0] : Dummy file | |
| Sources are: | |
| source[0] : Pickle file | |
| """ | |
| src_dir = os.path.dirname(str(source[0])) | |
| config = tests.ClassicConfig(*src_dir.split('/')[-6:]) | |
| test = tests.ClassicTest(source[0].abspath, src_dir, config) | |
| ref_dir = test.ref_dir | |
| with open(source[0].abspath, "rb") as fin: | |
| result = pickle.load(fin) | |
| assert len(result) == 1 | |
| result = result[0] | |
| if result.skipped(): | |
| print("*** %s: %s: Test skipped, not updating." % | |
| (source[0].dir, color_message(termcap.Yellow, "WARNING"))) | |
| return 0 | |
| elif result: | |
| print("*** %s: %s: Test successful, not updating." % | |
| (source[0].dir, color_message(termcap.Green, "skipped"))) | |
| return 0 | |
| elif result.failed_run(): | |
| print("*** %s: %s: Test failed, not updating." % | |
| (source[0].dir, color_message(termcap.Red, "ERROR"))) | |
| return 1 | |
| print("** Updating %s" % test) | |
| test.update_ref() | |
| return 0 | |
| def update_test_string(target, source, env): | |
| return env.subst("Updating ${SOURCES[0].dir}", | |
| target=target, source=source) | |
| updateAction = env.Action(update_test, update_test_string) | |
| def test_builder(test_tuple): | |
| """Define a test.""" | |
| out_dir = "/".join(test_tuple) | |
| binary = env.M5Binary.abspath | |
| test = tests.ClassicTest(binary, out_dir, test_tuple) | |
| def tgt(name): | |
| return os.path.join(out_dir, name) | |
| def ref(name): | |
| return os.path.join(test.ref_dir, name) | |
| pickle_file = tgt("status.pickle") | |
| targets = [ | |
| pickle_file, | |
| ] | |
| sources = [ | |
| env.M5Binary, | |
| "run.py", | |
| ] + [ ref(f) for f in test.ref_files() ] | |
| env.Command(targets, sources, testAction) | |
| # phony target to echo status | |
| if GetOption('update_ref'): | |
| p = env.Command(tgt("_update"), [pickle_file], updateAction) | |
| else: | |
| p = env.Command(tgt("_print"), [pickle_file], printAction) | |
| env.AlwaysBuild(p) | |
| def list_tests(target, source, env): | |
| """Create a list of tests | |
| Targets are as follows: | |
| target[0] : List file (e.g., tests/opt/all.list, tests/opt/quick.list) | |
| Sources are: - | |
| """ | |
| tgt_name = os.path.basename(str(target[0])) | |
| base, ext = os.path.splitext(tgt_name) | |
| categories = tests.all_categories if base == "all" else (base, ) | |
| with open(target[0].abspath, "w") as fout: | |
| for cat in categories: | |
| for test in env.Tests[cat]: | |
| print("/".join(test), file=fout) | |
| return 0 | |
| testListAction = env.Action(list_tests, strfunction=None) | |
| env.Command("all.list", tuple(), testListAction) | |
| for cat, test_list in env.Tests.items(): | |
| env.Command("%s.list" % cat, tuple(), testListAction) | |
| for test in test_list: | |
| test_builder(test) |