+++ /dev/null
-#!/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.
-
-from __future__ import print_function
-
-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):
- if not os.path.isfile(args.gem5) or not os.access(args.gem5, os.X_OK):
- print("gem5 binary '%s' not an executable file" % args.gem5,
- file=sys.stderr)
- sys.exit(2)
-
- 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):
- def _load(f):
- # Load the pickled status file, sometimes e.g., when a
- # regression is still running the status file might be
- # incomplete.
- try:
- return pickle.load(f)
- except EOFError:
- print('Could not read file %s' % f.name, file=sys.stderr)
- return []
-
- formatter = _create_formatter(args)
- suites = sum([ _load(f) for f in args.result ], [])
- formatter.dump_suites(suites)
-
-def _test_args(subparsers):
- parser = subparsers.add_parser(
- "test",
- formatter_class=ParagraphHelpFormatter,
- help='Probe test results and set exit code',
- epilog="""
-
- Load one or more pickled test file and return an exit code
- corresponding to the test outcome. The following exit codes
- can be returned:
-
- 0: All tests were successful or skipped.
-
- 1: General fault in the script such as incorrect parameters or
- failing to parse a pickle file.
-
- 2: At least one test failed to run. This is what the summary
- formatter usually shows as a 'FAILED'.
-
- 3: All tests ran correctly, but at least one failed to
- verify its output. When displaying test output using the
- summary formatter, such a test would show up as 'CHANGED'.
- """)
-
- parser.add_argument("result", type=argparse.FileType("rb"), nargs="*",
- help="Pickled test results")
-
-def _test(args):
- try:
- suites = sum([ pickle.load(f) for f in args.result ], [])
- except EOFError:
- print('Could not read all files', file=sys.stderr)
- sys.exit(2)
-
- if all(s for s in suites):
- sys.exit(0)
- elif any([ s.failed_run() for s in suites ]):
- sys.exit(2)
- elif any([ s.changed() for s in suites ]):
- sys.exit(3)
- else:
- assert False, "Unexpected return status from test"
-
-_commands = {
- "list" : (_list_tests, _list_tests_args),
- "run" : (_run_tests, _run_tests_args),
- "show" : (_show, _show_args),
- "test" : (_test, _test_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()