Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2013 The Chromium Authors. All rights reserved. | 3 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Runs all types of tests from one unified interface.""" | 7 """Runs all types of tests from one unified interface.""" |
| 8 | 8 |
| 9 import argparse | 9 import argparse |
| 10 import collections | 10 import collections |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 if args.output_directory: | 112 if args.output_directory: |
| 113 constants.SetOutputDirectort(args.output_directory) | 113 constants.SetOutputDirectort(args.output_directory) |
| 114 if args.adb_path: | 114 if args.adb_path: |
| 115 constants.SetAdbPath(args.adb_path) | 115 constants.SetAdbPath(args.adb_path) |
| 116 # Some things such as Forwarder require ADB to be in the environment path. | 116 # Some things such as Forwarder require ADB to be in the environment path. |
| 117 adb_dir = os.path.dirname(constants.GetAdbPath()) | 117 adb_dir = os.path.dirname(constants.GetAdbPath()) |
| 118 if adb_dir and adb_dir not in os.environ['PATH'].split(os.pathsep): | 118 if adb_dir and adb_dir not in os.environ['PATH'].split(os.pathsep): |
| 119 os.environ['PATH'] = adb_dir + os.pathsep + os.environ['PATH'] | 119 os.environ['PATH'] = adb_dir + os.pathsep + os.environ['PATH'] |
| 120 | 120 |
| 121 | 121 |
| 122 def AddRemoteDeviceOptions(parser): | |
| 123 group = parser.add_argument_group('Remote Device Options') | |
| 124 api_secret_group = group.add_mutually_exclusive_group() | |
| 125 api_key_group = group.add_mutually_exclusive_group() | |
| 126 | |
| 127 group.add_argument('--trigger', default='', | |
| 128 help=('Only triggers the test if set. Stores test_run_id ' | |
| 129 'in given file path. ')) | |
| 130 group.add_argument('--collect', default='', | |
| 131 help=('Only collects the test results if set. ' | |
| 132 'Gets test_run_id from given file path.')) | |
| 133 group.add_argument('--remote-device', default='Nexus 5', | |
| 134 help=('Device type to run test on.')) | |
| 135 group.add_argument('--remote-device-os', default='4.4.2', | |
| 136 help=('OS to have on the device.')) | |
| 137 api_key_group.add_argument('--api-key', default='', | |
|
jbudorick
2014/12/04 21:51:34
nit: handle api_key_group and api_secret_group all
rnephew (Reviews Here)
2014/12/04 23:16:50
Done.
| |
| 138 help=('API key for remote devices. Overrides api-key-file')) | |
| 139 api_secret_group.add_argument('--api-secret', default='', | |
| 140 help=('API secret for remote devices. ' | |
| 141 'Overrides api-secret-file')) | |
| 142 api_key_group.add_argument('--api-key-file', default='', | |
| 143 help=('Path to file that contains API key.')) | |
| 144 api_secret_group.add_argument('--api-secret-file', default='', | |
| 145 help=('Path to file that contains API secret.')) | |
| 146 group.add_argument('--results-path', default='', | |
| 147 help=('File path to download results to.')) | |
| 148 group.add_argument('--api-protocol', default='http', | |
| 149 help=('HTTP protocol to use. (http or https)')) | |
| 150 group.add_argument('--api-address', default='172.22.21.180', | |
| 151 help=('Address to send HTTP requests.')) | |
| 152 group.add_argument('--api-port', default='80', | |
| 153 help=('Port to send HTTP requests to.')) | |
| 154 group.add_argument('--runner-type', default='', | |
| 155 help=('Type of test to run as.')) | |
| 156 group.add_argument('--runner-package', default='', | |
| 157 help=('Package name of test.')) | |
| 158 group.add_argument('--apk-under-test', default='apks/Chrome.apk', | |
| 159 help=('APK to run tests on.')) | |
| 160 | |
| 161 | |
| 122 def AddDeviceOptions(parser): | 162 def AddDeviceOptions(parser): |
| 123 """Adds device options to |parser|.""" | 163 """Adds device options to |parser|.""" |
| 124 group = parser.add_argument_group(title='Device Options') | 164 group = parser.add_argument_group(title='Device Options') |
| 125 group.add_argument('-c', dest='cleanup_test_files', | 165 group.add_argument('-c', dest='cleanup_test_files', |
| 126 help='Cleanup test files on the device after run', | 166 help='Cleanup test files on the device after run', |
| 127 action='store_true') | 167 action='store_true') |
| 128 group.add_argument('--tool', | 168 group.add_argument('--tool', |
| 129 dest='tool', | 169 dest='tool', |
| 130 help=('Run the test under a tool ' | 170 help=('Run the test under a tool ' |
| 131 '(use --tool help to list them)')) | 171 '(use --tool help to list them)')) |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 159 group.add_argument('-t', dest='timeout', type=int, default=60, | 199 group.add_argument('-t', dest='timeout', type=int, default=60, |
| 160 help='Timeout to wait for each test ' | 200 help='Timeout to wait for each test ' |
| 161 '(default: %(default)s).') | 201 '(default: %(default)s).') |
| 162 group.add_argument('--isolate_file_path', | 202 group.add_argument('--isolate_file_path', |
| 163 '--isolate-file-path', | 203 '--isolate-file-path', |
| 164 dest='isolate_file_path', | 204 dest='isolate_file_path', |
| 165 help='.isolate file path to override the default ' | 205 help='.isolate file path to override the default ' |
| 166 'path') | 206 'path') |
| 167 AddDeviceOptions(parser) | 207 AddDeviceOptions(parser) |
| 168 AddCommonOptions(parser) | 208 AddCommonOptions(parser) |
| 209 AddRemoteDeviceOptions(parser) | |
| 169 | 210 |
| 170 | 211 |
| 171 def AddLinkerTestOptions(parser): | 212 def AddLinkerTestOptions(parser): |
| 172 group = parser.add_argument_group('Linker Test Options') | 213 group = parser.add_argument_group('Linker Test Options') |
| 173 group.add_argument('-f', '--gtest-filter', dest='test_filter', | 214 group.add_argument('-f', '--gtest-filter', dest='test_filter', |
| 174 help='googletest-style filter string.') | 215 help='googletest-style filter string.') |
| 175 AddCommonOptions(parser) | 216 AddCommonOptions(parser) |
| 176 AddDeviceOptions(parser) | 217 AddDeviceOptions(parser) |
| 177 | 218 |
| 178 | 219 |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 419 '--seed', type=int, | 460 '--seed', type=int, |
| 420 help=('Seed value for pseudo-random generator. Same seed value generates ' | 461 help=('Seed value for pseudo-random generator. Same seed value generates ' |
| 421 'the same sequence of events. Seed is randomized by default.')) | 462 'the same sequence of events. Seed is randomized by default.')) |
| 422 group.add_argument( | 463 group.add_argument( |
| 423 '--extra-args', default='', | 464 '--extra-args', default='', |
| 424 help=('String of other args to pass to the command verbatim.')) | 465 help=('String of other args to pass to the command verbatim.')) |
| 425 | 466 |
| 426 AddCommonOptions(parser) | 467 AddCommonOptions(parser) |
| 427 AddDeviceOptions(parser) | 468 AddDeviceOptions(parser) |
| 428 | 469 |
| 429 | |
| 430 def ProcessMonkeyTestOptions(args): | 470 def ProcessMonkeyTestOptions(args): |
| 431 """Processes all monkey test options. | 471 """Processes all monkey test options. |
| 432 | 472 |
| 433 Args: | 473 Args: |
| 434 args: argparse.Namespace object. | 474 args: argparse.Namespace object. |
| 435 | 475 |
| 436 Returns: | 476 Returns: |
| 437 A MonkeyOptions named tuple which contains all options relevant to | 477 A MonkeyOptions named tuple which contains all options relevant to |
| 438 monkey tests. | 478 monkey tests. |
| 439 """ | 479 """ |
| 440 # TODO(jbudorick): Handle this directly in argparse with nargs='+' | 480 # TODO(jbudorick): Handle this directly in argparse with nargs='+' |
| 441 category = args.category | 481 category = args.category |
| 442 if category: | 482 if category: |
| 443 category = args.category.split(',') | 483 category = args.category.split(',') |
| 444 | 484 |
| 445 # TODO(jbudorick): Get rid of MonkeyOptions. | 485 # TODO(jbudorick): Get rid of MonkeyOptions. |
| 446 return monkey_test_options.MonkeyOptions( | 486 return monkey_test_options.MonkeyOptions( |
| 447 args.verbose_count, | 487 args.verbose_count, |
| 448 args.package, | 488 args.package, |
| 449 args.event_count, | 489 args.event_count, |
| 450 category, | 490 category, |
| 451 args.throttle, | 491 args.throttle, |
| 452 args.seed, | 492 args.seed, |
| 453 args.extra_args) | 493 args.extra_args) |
| 454 | 494 |
| 495 def AddUirobotTestOptions(parser): | |
| 496 """Adds uirobot test options to |option_parser|.""" | |
| 497 group = parser.add_argument_group('Uirobot Test Options') | |
| 498 | |
| 499 group.add_argument( | |
| 500 '--minutes', default=5, type=int, | |
| 501 help='Number of minutes to run uirobot test [default: %default].') | |
| 502 | |
| 503 AddCommonOptions(parser) | |
| 504 AddDeviceOptions(parser) | |
| 505 AddRemoteDeviceOptions(parser) | |
| 455 | 506 |
| 456 def AddPerfTestOptions(parser): | 507 def AddPerfTestOptions(parser): |
| 457 """Adds perf test options to |parser|.""" | 508 """Adds perf test options to |parser|.""" |
| 458 | 509 |
| 459 group = parser.add_argument_group('Perf Test Options') | 510 group = parser.add_argument_group('Perf Test Options') |
| 460 | 511 |
| 461 class SingleStepAction(argparse.Action): | 512 class SingleStepAction(argparse.Action): |
| 462 def __call__(self, parser, namespace, values, option_string=None): | 513 def __call__(self, parser, namespace, values, option_string=None): |
| 463 if values and not namespace.single_step: | 514 if values and not namespace.single_step: |
| 464 parser.error('single step command provided, ' | 515 parser.error('single step command provided, ' |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 805 | 856 |
| 806 Raises: | 857 Raises: |
| 807 Exception: Unknown command name passed in, or an exception from an | 858 Exception: Unknown command name passed in, or an exception from an |
| 808 individual test runner. | 859 individual test runner. |
| 809 """ | 860 """ |
| 810 command = args.command | 861 command = args.command |
| 811 | 862 |
| 812 ProcessCommonOptions(args) | 863 ProcessCommonOptions(args) |
| 813 | 864 |
| 814 if args.enable_platform_mode: | 865 if args.enable_platform_mode: |
| 815 return RunTestsInPlatformMode(args, parser.error) | 866 return RunTestsInPlatformMode(args, parser) |
| 816 | 867 |
| 817 if command in constants.LOCAL_MACHINE_TESTS: | 868 if command in constants.LOCAL_MACHINE_TESTS: |
| 818 devices = [] | 869 devices = [] |
| 819 else: | 870 else: |
| 820 devices = _GetAttachedDevices(args.test_device) | 871 devices = _GetAttachedDevices(args.test_device) |
| 821 | 872 |
| 822 forwarder.Forwarder.RemoveHostLog() | 873 forwarder.Forwarder.RemoveHostLog() |
| 823 if not ports.ResetTestServerPortAllocation(): | 874 if not ports.ResetTestServerPortAllocation(): |
| 824 raise Exception('Failed to reset test server port.') | 875 raise Exception('Failed to reset test server port.') |
| 825 | 876 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 838 elif command == 'perf': | 889 elif command == 'perf': |
| 839 return _RunPerfTests(args) | 890 return _RunPerfTests(args) |
| 840 elif command == 'python': | 891 elif command == 'python': |
| 841 return _RunPythonTests(args) | 892 return _RunPythonTests(args) |
| 842 else: | 893 else: |
| 843 raise Exception('Unknown test type.') | 894 raise Exception('Unknown test type.') |
| 844 | 895 |
| 845 | 896 |
| 846 _SUPPORTED_IN_PLATFORM_MODE = [ | 897 _SUPPORTED_IN_PLATFORM_MODE = [ |
| 847 # TODO(jbudorick): Add support for more test types. | 898 # TODO(jbudorick): Add support for more test types. |
| 848 'gtest', | 899 'gtest', 'uirobot', |
| 849 ] | 900 ] |
| 850 | 901 |
| 851 | 902 |
| 852 def RunTestsInPlatformMode(args, parser): | 903 def RunTestsInPlatformMode(args, parser): |
| 853 | 904 |
| 854 if args.command not in _SUPPORTED_IN_PLATFORM_MODE: | 905 if args.command not in _SUPPORTED_IN_PLATFORM_MODE: |
| 855 parser.error('%s is not yet supported in platform mode' % args.command) | 906 parser.error('%s is not yet supported in platform mode' % args.command) |
| 856 | 907 |
| 857 with environment_factory.CreateEnvironment(args, parser.error) as env: | 908 with environment_factory.CreateEnvironment(args, parser.error) as env: |
| 858 with test_instance_factory.CreateTestInstance(args, parser.error) as test: | 909 with test_instance_factory.CreateTestInstance(args, parser.error) as test: |
| 859 with test_run_factory.CreateTestRun( | 910 with test_run_factory.CreateTestRun( |
| 860 args, env, test, parser.error) as test_run: | 911 args, env, test, parser.error) as test_run: |
| 861 results = test_run.RunTests() | 912 results = test_run.RunTests() |
| 862 | 913 |
| 914 if args.trigger: | |
| 915 return # Not returning results, only triggering. | |
|
jbudorick
2014/12/04 21:51:34
return 0
rnephew (Reviews Here)
2014/12/04 23:16:50
Done.
| |
| 916 | |
| 863 report_results.LogFull( | 917 report_results.LogFull( |
| 864 results=results, | 918 results=results, |
| 865 test_type=test.TestType(), | 919 test_type=test.TestType(), |
| 866 test_package=test_run.TestPackage(), | 920 test_package=test_run.TestPackage(), |
| 867 annotation=args.annotations, | 921 annotation=args.annotations, |
| 868 flakiness_server=args.flakiness_dashboard_server) | 922 flakiness_server=args.flakiness_dashboard_server) |
| 869 | 923 |
| 870 if args.json_results_file: | 924 if args.json_results_file: |
| 871 json_results.GenerateJsonResultsFile( | 925 json_results.GenerateJsonResultsFile( |
| 872 results, args.json_results_file) | 926 results, args.json_results_file) |
| 873 | 927 |
| 874 return results | 928 return results |
|
jbudorick
2014/12/04 21:51:34
I feel like I've written this a bunch locally, but
rnephew (Reviews Here)
2014/12/04 23:16:50
Done.
| |
| 875 | 929 |
| 876 | 930 |
| 877 CommandConfigTuple = collections.namedtuple( | 931 CommandConfigTuple = collections.namedtuple( |
| 878 'CommandConfigTuple', | 932 'CommandConfigTuple', |
| 879 ['add_options_func', 'help_txt']) | 933 ['add_options_func', 'help_txt']) |
| 880 VALID_COMMANDS = { | 934 VALID_COMMANDS = { |
| 881 'gtest': CommandConfigTuple( | 935 'gtest': CommandConfigTuple( |
| 882 AddGTestOptions, | 936 AddGTestOptions, |
| 883 'googletest-based C++ tests'), | 937 'googletest-based C++ tests'), |
| 884 'instrumentation': CommandConfigTuple( | 938 'instrumentation': CommandConfigTuple( |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 895 "Tests based on Android's monkey"), | 949 "Tests based on Android's monkey"), |
| 896 'perf': CommandConfigTuple( | 950 'perf': CommandConfigTuple( |
| 897 AddPerfTestOptions, | 951 AddPerfTestOptions, |
| 898 'Performance tests'), | 952 'Performance tests'), |
| 899 'python': CommandConfigTuple( | 953 'python': CommandConfigTuple( |
| 900 AddPythonTestOptions, | 954 AddPythonTestOptions, |
| 901 'Python tests based on unittest.TestCase'), | 955 'Python tests based on unittest.TestCase'), |
| 902 'linker': CommandConfigTuple( | 956 'linker': CommandConfigTuple( |
| 903 AddLinkerTestOptions, | 957 AddLinkerTestOptions, |
| 904 'Linker tests'), | 958 'Linker tests'), |
| 959 'uirobot': CommandConfigTuple( | |
| 960 AddUirobotTestOptions, | |
| 961 'Uirobot test'), | |
| 905 } | 962 } |
| 906 | 963 |
| 907 | 964 |
| 908 def DumpThreadStacks(_signal, _frame): | 965 def DumpThreadStacks(_signal, _frame): |
| 909 for thread in threading.enumerate(): | 966 for thread in threading.enumerate(): |
| 910 reraiser_thread.LogThreadStack(thread) | 967 reraiser_thread.LogThreadStack(thread) |
| 911 | 968 |
| 912 | 969 |
| 913 def main(): | 970 def main(): |
| 914 signal.signal(signal.SIGUSR1, DumpThreadStacks) | 971 signal.signal(signal.SIGUSR1, DumpThreadStacks) |
| 915 | 972 |
| 916 parser = argparse.ArgumentParser() | 973 parser = argparse.ArgumentParser() |
| 917 command_parsers = parser.add_subparsers(title='test types', | 974 command_parsers = parser.add_subparsers(title='test types', |
| 918 dest='command') | 975 dest='command') |
| 919 | 976 |
| 920 for test_type, config in sorted(VALID_COMMANDS.iteritems(), | 977 for test_type, config in sorted(VALID_COMMANDS.iteritems(), |
| 921 key=lambda x: x[0]): | 978 key=lambda x: x[0]): |
| 922 subparser = command_parsers.add_parser( | 979 subparser = command_parsers.add_parser( |
| 923 test_type, usage='%(prog)s [options]', help=config.help_txt) | 980 test_type, usage='%(prog)s [options]', help=config.help_txt) |
| 924 config.add_options_func(subparser) | 981 config.add_options_func(subparser) |
| 925 | 982 |
| 926 args = parser.parse_args() | 983 args = parser.parse_args() |
| 927 return RunTestsCommand(args, parser) | 984 return RunTestsCommand(args, parser) |
| 928 | 985 |
| 929 | 986 |
| 930 if __name__ == '__main__': | 987 if __name__ == '__main__': |
| 931 sys.exit(main()) | 988 sys.exit(main()) |
| OLD | NEW |