summaryrefslogtreecommitdiff
path: root/tests/tests.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/tests.py')
-rwxr-xr-xtests/tests.py287
1 files changed, 287 insertions, 0 deletions
diff --git a/tests/tests.py b/tests/tests.py
new file mode 100755
index 000000000..05d68881e
--- /dev/null
+++ b/tests/tests.py
@@ -0,0 +1,287 @@
+#!/usr/bin/env 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.
+#
+# 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: Andreas Sandberg
+
+import argparse
+import sys
+import os
+import pickle
+
+from testing.tests import *
+import testing.results
+
+class ParagraphHelpFormatter(argparse.HelpFormatter):
+ def _fill_text(self, text, width, indent):
+ return "\n\n".join([
+ super(ParagraphHelpFormatter, self)._fill_text(p, width, indent) \
+ for p in text.split("\n\n") ])
+
+formatters = {
+ "junit" : testing.results.JUnit,
+ "text" : testing.results.Text,
+ "summary" : testing.results.TextSummary,
+ "pickle" : testing.results.Pickle,
+}
+
+
+def _add_format_args(parser):
+ parser.add_argument("--format", choices=formatters, default="text",
+ help="Output format")
+
+ parser.add_argument("--no-junit-xlate-names", action="store_true",
+ help="Don't translate test names to " \
+ "package-like names")
+
+ parser.add_argument("--output", "-o",
+ type=argparse.FileType('w'), default=sys.stdout,
+ help="Test result output file")
+
+
+def _create_formatter(args):
+ formatter = formatters[args.format]
+ kwargs = {
+ "fout" : args.output,
+ "verbose" : args.verbose
+ }
+
+ if issubclass(formatter, testing.results.JUnit):
+ kwargs.update({
+ "translate_names" : not args.no_junit_xlate_names,
+ })
+
+ return formatter(**kwargs)
+
+
+def _list_tests_args(subparsers):
+ parser = subparsers.add_parser(
+ "list",
+ formatter_class=ParagraphHelpFormatter,
+ help="List available tests",
+ description="List available tests",
+ epilog="""
+ Generate a list of available tests using a list filter.
+
+ The filter is a string consisting of the target ISA optionally
+ followed by the test category and mode separated by
+ slashes. The test names emitted by this command can be fed
+ into the run command.
+
+ For example, to list all quick arm tests, run the following:
+ tests.py list arm/quick
+
+ Non-mandatory parts of the filter string (anything other than
+ the ISA) can be left out or replaced with the wildcard
+ character. For example, all full-system tests can be listed
+ with this command: tests.py list arm/*/fs""")
+
+ parser.add_argument("--ruby-protocol", type=str, default=None,
+ help="Ruby protocol")
+
+ parser.add_argument("--gpu-isa", type=str, default=None,
+ help="GPU ISA")
+
+ parser.add_argument("list_filter", metavar="ISA[/category/mode]",
+ action="append", type=str,
+ help="List available test cases")
+
+def _list_tests(args):
+ for isa, categories, modes in \
+ ( parse_test_filter(f) for f in args.list_filter ):
+
+ for test in get_tests(isa, categories=categories, modes=modes,
+ ruby_protocol=args.ruby_protocol,
+ gpu_isa=args.gpu_isa):
+ print "/".join(test)
+ sys.exit(0)
+
+def _run_tests_args(subparsers):
+ parser = subparsers.add_parser(
+ "run",
+ formatter_class=ParagraphHelpFormatter,
+ help='Run one or more tests',
+ description="Run one or more tests.",
+ epilog="""
+ Run one or more tests described by a gem5 test tuple.
+
+ The test tuple consists of a test category (quick or long), a
+ test mode (fs or se), a workload name, an isa, an operating
+ system, and a config name separate by slashes. For example:
+ quick/se/00.hello/arm/linux/simple-timing
+
+ Available tests can be listed using the 'list' sub-command
+ (e.g., "tests.py list arm/quick" or one of the scons test list
+ targets (e.g., "scons build/ARM/tests/opt/quick.list").
+
+ The test results can be stored in multiple different output
+ formats. See the help for the show command for more details
+ about output formatting.""")
+
+ parser.add_argument("gem5", type=str,
+ help="gem5 binary")
+
+ parser.add_argument("test", type=str, nargs="*",
+ help="List of tests to execute")
+
+ parser.add_argument("--directory", "-d",
+ type=str, default="m5tests",
+ help="Test work directory")
+
+ parser.add_argument("--timeout", "-t",
+ type=int, default="0", metavar="MINUTES",
+ help="Timeout, 0 to disable")
+
+ parser.add_argument("--skip-diff-out", action="store_true",
+ help="Skip output diffing stage")
+
+ parser.add_argument("--skip-diff-stat", action="store_true",
+ help="Skip stat diffing stage")
+
+ _add_format_args(parser)
+
+def _run_tests(args):
+ formatter = _create_formatter(args)
+
+ out_base = os.path.abspath(args.directory)
+ if not os.path.exists(out_base):
+ os.mkdir(out_base)
+ tests = []
+ for test_name in args.test:
+ config = ClassicConfig(*test_name.split("/"))
+ out_dir = os.path.join(out_base, "/".join(config))
+ tests.append(
+ ClassicTest(args.gem5, out_dir, config,
+ timeout=args.timeout,
+ skip_diff_stat=args.skip_diff_stat,
+ skip_diff_out=args.skip_diff_out))
+
+ all_results = []
+ print "Running %i tests" % len(tests)
+ for testno, test in enumerate(tests):
+ print "%i: Running '%s'..." % (testno, test)
+
+ all_results.append(test.run())
+
+ formatter.dump_suites(all_results)
+
+def _show_args(subparsers):
+ parser = subparsers.add_parser(
+ "show",
+ formatter_class=ParagraphHelpFormatter,
+ help='Display pickled test results',
+ description='Display pickled test results',
+ epilog="""
+ Reformat the pickled output from one or more test runs. This
+ command is typically used with the output from a single test
+ run, but it can also be used to merge the outputs from
+ multiple runs.
+
+ The 'text' format is a verbose output format that provides
+ information about individual test units and the output from
+ failed tests. It's mainly useful for debugging test failures.
+
+ The 'summary' format provides outputs the results of one test
+ per line with the test's overall status (OK, SKIPPED, or
+ FAILED).
+
+ The 'junit' format is primarily intended for use with CI
+ systems. It provides an XML representation of test
+ status. Similar to the text format, it includes detailed
+ information about test failures. Since many JUnit parser make
+ assume that test names look like Java packet strings, the
+ JUnit formatter automatically to something the looks like a
+ Java class path ('.'->'-', '/'->'.').
+
+ The 'pickle' format stores the raw results in a format that
+ can be reformatted using this command. It's typically used
+ with the show command to merge multiple test results into one
+ pickle file.""")
+
+ _add_format_args(parser)
+
+ parser.add_argument("result", type=argparse.FileType("rb"), nargs="*",
+ help="Pickled test results")
+
+def _show(args):
+ formatter = _create_formatter(args)
+ suites = sum([ pickle.load(f) for f in args.result ], [])
+ formatter.dump_suites(suites)
+
+_commands = {
+ "list" : (_list_tests, _list_tests_args),
+ "run" : (_run_tests, _run_tests_args),
+ "show" : (_show, _show_args),
+}
+
+def main():
+ parser = argparse.ArgumentParser(
+ formatter_class=ParagraphHelpFormatter,
+ description="""gem5 testing multi tool.""",
+ epilog="""
+ This tool provides an interface to gem5's test framework that
+ doesn't depend on gem5's build system. It supports test
+ listing, running, and output formatting.
+
+ The list sub-command (e.g., "test.py list arm/quick") produces
+ a list of tests tuples that can be used by the run command
+ (e.g., "tests.py run gem5.opt
+ quick/se/00.hello/arm/linux/simple-timing").
+
+ The run command supports several output formats. One of them,
+ pickle, contains the raw output from the tests and can be
+ re-formatted using the show command (e.g., "tests.py show
+ --format summary *.pickle"). Such pickle files are also
+ generated by the build system when scons is used to run
+ regressions.
+
+ See the usage strings for the individual sub-commands for
+ details.""")
+
+ parser.add_argument("--verbose", action="store_true",
+ help="Produce more verbose output")
+
+ subparsers = parser.add_subparsers(dest="command")
+
+ for key, (impl, cmd_parser) in _commands.items():
+ cmd_parser(subparsers)
+
+ args = parser.parse_args()
+ impl, cmd_parser = _commands[args.command]
+ impl(args)
+
+if __name__ == "__main__":
+ main()