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