| #!/usr/bin/env python3 |
| |
| # Copyright 2019 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| #### CATEGORY=Other |
| |
| import argparse |
| import json |
| import os |
| import subprocess |
| import sys |
| import textwrap |
| |
| # Colors and helpers for terminal pretty-printing. |
| BOLD_BLACK = '\033[1;30m' |
| BOLD_RED = '\033[1;31m' |
| NO_COLOR = '\033[0m' |
| def info_print(s): |
| print('\n%s%s%s' % (BOLD_BLACK, s, NO_COLOR)) |
| def error_print(s): |
| print('\n%s%s%s' % (BOLD_RED, s, NO_COLOR)) |
| |
| def main(): |
| parser = argparse.ArgumentParser( |
| description=(textwrap.dedent('''\ |
| Executes a test in the GN graph. |
| |
| Note that the name of the test is just the name of a binary in the |
| output folder. |
| For example, if you have this binary: |
| |
| out/default/host_x64/my_test |
| |
| You just specify "my_test" as the test name. |
| |
| Also note that the binary need to be part of your GN build graph, |
| even if you are not interested in delivering this binary as part of |
| the image. This means that, if your test is generated by the |
| |
| //system/src/my_package/my_test |
| |
| target, you might need to add this target to your GN build graph by |
| adjusting your "fx set" arguments like this: |
| |
| fx set ... --with //system/src/my_package/my_test |
| ''')), |
| formatter_class=argparse.RawDescriptionHelpFormatter, |
| ) |
| parser.add_argument('--manifest', |
| help='The path to the manifest of tests', |
| required=True) |
| parser.add_argument('--names', |
| help='The names of the tests to execute', |
| nargs='*', |
| required=True) |
| parser.add_argument('test_args', |
| help='Arguments to pass to the tests on execution', |
| nargs='*') |
| parser.add_argument('--build-dir', |
| help='The path to the root build directory', |
| required=True) |
| parser.add_argument('--ninja', |
| help='The path to the ninja binary', |
| required=True) |
| args = parser.parse_args() |
| |
| if not args.names: |
| error_print('no tests provided') |
| return 1 |
| |
| with open(args.manifest, 'r') as f: |
| entries = json.load(f) |
| |
| tests = [] |
| unmatched = set(args.names) |
| for entry in entries: |
| test = entry['test'] |
| if test['os'] == 'fuchsia': |
| continue |
| # some tests have no "path" property |
| if 'path' not in test: |
| continue |
| path = test['path'] |
| name = os.path.basename(path) |
| if name not in args.names: |
| continue |
| tests.append(test) |
| unmatched.remove(name) |
| |
| if unmatched: |
| error_print( |
| 'could not find tests with the following names:\n' + |
| '\n'.join(unmatched)) |
| return 1 |
| |
| # test['path'] gives the path to the test relative build directory, |
| # which is a valid ninja target. |
| ret = subprocess.call( |
| [args.ninja, '-C', args.build_dir] + |
| [test['path'] for test in tests]) |
| if ret: |
| error_print('failed to compile tests') |
| return 1 |
| |
| failed = [] |
| for test in tests: |
| target = test['name'] |
| info_print('<< running %s >>' % target) |
| if 'command' in test and len(test['command']) > 1: |
| location, extra_args = test['command'][0], test['command'][1:] |
| else: |
| location, extra_args = test['path'], [] |
| ret = subprocess.call( |
| [os.path.join(args.build_dir, location)] + extra_args + args.test_args) |
| if ret != 0: |
| failed.append(target) |
| |
| num_tests = len(tests) |
| if not num_tests: |
| error_print('no tests found with names %s' % ', '.join(args.names)) |
| return 1 |
| |
| if failed: |
| error_print( |
| '%d of %d test%s failed:' % ( |
| len(failed), num_tests, 's' if num_tests > 1 else '' |
| ) + |
| '\n'.join(failed)) |
| return 1 |
| else: |
| info_print('%d of %d test%s passed' % ( |
| num_tests, num_tests, 's' if num_tests > 1 else '')) |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |