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 collections | 9 import collections |
10 import logging | 10 import logging |
11 import optparse | 11 import optparse |
12 import os | 12 import os |
13 import shutil | 13 import shutil |
14 import signal | 14 import signal |
15 import sys | 15 import sys |
16 import threading | 16 import threading |
| 17 import traceback |
17 | 18 |
18 from pylib import android_commands | 19 from pylib import android_commands |
19 from pylib import constants | 20 from pylib import constants |
20 from pylib import forwarder | 21 from pylib import forwarder |
21 from pylib import ports | 22 from pylib import ports |
22 from pylib.base import base_test_result | 23 from pylib.base import base_test_result |
23 from pylib.base import test_dispatcher | 24 from pylib.base import test_dispatcher |
24 from pylib.gtest import gtest_config | 25 from pylib.gtest import gtest_config |
25 from pylib.gtest import setup as gtest_setup | 26 from pylib.gtest import setup as gtest_setup |
26 from pylib.gtest import test_options as gtest_test_options | 27 from pylib.gtest import test_options as gtest_test_options |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 option_parser.add_option('--test_data', action='append', default=[], | 180 option_parser.add_option('--test_data', action='append', default=[], |
180 help=('Each instance defines a directory of test ' | 181 help=('Each instance defines a directory of test ' |
181 'data that should be copied to the target(s) ' | 182 'data that should be copied to the target(s) ' |
182 'before running the tests. The argument ' | 183 'before running the tests. The argument ' |
183 'should be of the form <target>:<source>, ' | 184 'should be of the form <target>:<source>, ' |
184 '<target> is relative to the device data' | 185 '<target> is relative to the device data' |
185 'directory, and <source> is relative to the ' | 186 'directory, and <source> is relative to the ' |
186 'chromium build directory.')) | 187 'chromium build directory.')) |
187 | 188 |
188 | 189 |
189 def ProcessJavaTestOptions(options): | 190 def ProcessJavaTestOptions(options, error_func): |
190 """Processes options/arguments and populates |options| with defaults.""" | 191 """Processes options/arguments and populates |options| with defaults.""" |
191 | 192 |
192 if options.annotation_str: | 193 if options.annotation_str: |
193 options.annotations = options.annotation_str.split(',') | 194 options.annotations = options.annotation_str.split(',') |
194 elif options.test_filter: | 195 elif options.test_filter: |
195 options.annotations = [] | 196 options.annotations = [] |
196 else: | 197 else: |
197 options.annotations = ['Smoke', 'SmallTest', 'MediumTest', 'LargeTest', | 198 options.annotations = ['Smoke', 'SmallTest', 'MediumTest', 'LargeTest', |
198 'EnormousTest'] | 199 'EnormousTest'] |
199 | 200 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 | 239 |
239 Args: | 240 Args: |
240 options: optparse.Options object. | 241 options: optparse.Options object. |
241 error_func: Function to call with the error message in case of an error. | 242 error_func: Function to call with the error message in case of an error. |
242 | 243 |
243 Returns: | 244 Returns: |
244 An InstrumentationOptions named tuple which contains all options relevant to | 245 An InstrumentationOptions named tuple which contains all options relevant to |
245 instrumentation tests. | 246 instrumentation tests. |
246 """ | 247 """ |
247 | 248 |
248 ProcessJavaTestOptions(options) | 249 ProcessJavaTestOptions(options, error_func) |
249 | 250 |
250 if options.java_only and options.python_only: | 251 if options.java_only and options.python_only: |
251 error_func('Options java_only (-j) and python_only (-p) ' | 252 error_func('Options java_only (-j) and python_only (-p) ' |
252 'are mutually exclusive.') | 253 'are mutually exclusive.') |
253 options.run_java_tests = True | 254 options.run_java_tests = True |
254 options.run_python_tests = True | 255 options.run_python_tests = True |
255 if options.java_only: | 256 if options.java_only: |
256 options.run_python_tests = False | 257 options.run_python_tests = False |
257 elif options.python_only: | 258 elif options.python_only: |
258 options.run_java_tests = False | 259 options.run_java_tests = False |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 | 317 |
317 Args: | 318 Args: |
318 options: optparse.Options object. | 319 options: optparse.Options object. |
319 error_func: Function to call with the error message in case of an error. | 320 error_func: Function to call with the error message in case of an error. |
320 | 321 |
321 Returns: | 322 Returns: |
322 A UIAutomatorOptions named tuple which contains all options relevant to | 323 A UIAutomatorOptions named tuple which contains all options relevant to |
323 uiautomator tests. | 324 uiautomator tests. |
324 """ | 325 """ |
325 | 326 |
326 ProcessJavaTestOptions(options) | 327 ProcessJavaTestOptions(options, error_func) |
327 | 328 |
328 if not options.package: | 329 if not options.package: |
329 error_func('--package is required.') | 330 error_func('--package is required.') |
330 | 331 |
331 if options.package not in constants.PACKAGE_INFO: | 332 if options.package not in constants.PACKAGE_INFO: |
332 error_func('Invalid package.') | 333 error_func('Invalid package.') |
333 | 334 |
334 if not options.test_jar: | 335 if not options.test_jar: |
335 error_func('--test-jar must be specified.') | 336 error_func('--test-jar must be specified.') |
336 | 337 |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 error_func('Please specify one of: --steps, --print-step, --single-step.') | 483 error_func('Please specify one of: --steps, --print-step, --single-step.') |
483 single_step = None | 484 single_step = None |
484 if options.single_step: | 485 if options.single_step: |
485 single_step = ' '.join(args[2:]) | 486 single_step = ' '.join(args[2:]) |
486 return perf_test_options.PerfOptions( | 487 return perf_test_options.PerfOptions( |
487 options.steps, options.flaky_steps, options.print_step, | 488 options.steps, options.flaky_steps, options.print_step, |
488 options.no_timeout, options.test_filter, options.dry_run, | 489 options.no_timeout, options.test_filter, options.dry_run, |
489 single_step) | 490 single_step) |
490 | 491 |
491 | 492 |
492 def _RunGTests(options, devices): | 493 def _RunGTests(options, error_func, devices): |
493 """Subcommand of RunTestsCommands which runs gtests.""" | 494 """Subcommand of RunTestsCommands which runs gtests.""" |
494 ProcessGTestOptions(options) | 495 ProcessGTestOptions(options) |
495 | 496 |
496 exit_code = 0 | 497 exit_code = 0 |
497 for suite_name in options.suite_name: | 498 for suite_name in options.suite_name: |
498 # TODO(gkanwar): Move this into ProcessGTestOptions once we require -s for | 499 # TODO(gkanwar): Move this into ProcessGTestOptions once we require -s for |
499 # the gtest command. | 500 # the gtest command. |
500 gtest_options = gtest_test_options.GTestOptions( | 501 gtest_options = gtest_test_options.GTestOptions( |
501 options.tool, | 502 options.tool, |
502 options.cleanup_test_files, | 503 options.cleanup_test_files, |
(...skipping 17 matching lines...) Expand all Loading... |
520 test_type='Unit test', | 521 test_type='Unit test', |
521 test_package=suite_name, | 522 test_package=suite_name, |
522 flakiness_server=options.flakiness_dashboard_server) | 523 flakiness_server=options.flakiness_dashboard_server) |
523 | 524 |
524 if os.path.isdir(constants.ISOLATE_DEPS_DIR): | 525 if os.path.isdir(constants.ISOLATE_DEPS_DIR): |
525 shutil.rmtree(constants.ISOLATE_DEPS_DIR) | 526 shutil.rmtree(constants.ISOLATE_DEPS_DIR) |
526 | 527 |
527 return exit_code | 528 return exit_code |
528 | 529 |
529 | 530 |
530 def _RunLinkerTests(options, devices): | 531 def _RunLinkerTests(options, error_func, devices): |
531 """Subcommand of RunTestsCommands which runs linker tests.""" | 532 """Subcommand of RunTestsCommands which runs linker tests.""" |
532 runner_factory, tests = linker_setup.Setup(options, devices) | 533 runner_factory, tests = linker_setup.Setup(options, devices) |
533 | 534 |
534 results, exit_code = test_dispatcher.RunTests( | 535 results, exit_code = test_dispatcher.RunTests( |
535 tests, runner_factory, devices, shard=True, test_timeout=60, | 536 tests, runner_factory, devices, shard=True, test_timeout=60, |
536 num_retries=options.num_retries) | 537 num_retries=options.num_retries) |
537 | 538 |
538 report_results.LogFull( | 539 report_results.LogFull( |
539 results=results, | 540 results=results, |
540 test_type='Linker test', | 541 test_type='Linker test', |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 | 707 |
707 ProcessCommonOptions(options) | 708 ProcessCommonOptions(options) |
708 | 709 |
709 devices = _GetAttachedDevices(options.test_device) | 710 devices = _GetAttachedDevices(options.test_device) |
710 | 711 |
711 forwarder.Forwarder.RemoveHostLog() | 712 forwarder.Forwarder.RemoveHostLog() |
712 if not ports.ResetTestServerPortAllocation(): | 713 if not ports.ResetTestServerPortAllocation(): |
713 raise Exception('Failed to reset test server port.') | 714 raise Exception('Failed to reset test server port.') |
714 | 715 |
715 if command == 'gtest': | 716 if command == 'gtest': |
716 return _RunGTests(options, devices) | 717 return _RunGTests(options, option_parser.error, devices) |
717 elif command == 'linker': | 718 elif command == 'linker': |
718 return _RunLinkerTests(options, devices) | 719 return _RunLinkerTests(options, option_parser.error, devices) |
719 elif command == 'instrumentation': | 720 elif command == 'instrumentation': |
720 return _RunInstrumentationTests(options, option_parser.error, devices) | 721 return _RunInstrumentationTests(options, option_parser.error, devices) |
721 elif command == 'uiautomator': | 722 elif command == 'uiautomator': |
722 return _RunUIAutomatorTests(options, option_parser.error, devices) | 723 return _RunUIAutomatorTests(options, option_parser.error, devices) |
723 elif command == 'monkey': | 724 elif command == 'monkey': |
724 return _RunMonkeyTests(options, option_parser.error, devices) | 725 return _RunMonkeyTests(options, option_parser.error, devices) |
725 elif command == 'perf': | 726 elif command == 'perf': |
726 return _RunPerfTests(options, args, option_parser.error, devices) | 727 return _RunPerfTests(options, args, option_parser.error, devices) |
727 else: | 728 else: |
728 raise Exception('Unknown test type.') | 729 raise Exception('Unknown test type.') |
729 | 730 |
730 | 731 |
731 def HelpCommand(command, _options, args, option_parser): | 732 def HelpCommand(command, options, args, option_parser): |
732 """Display help for a certain command, or overall help. | 733 """Display help for a certain command, or overall help. |
733 | 734 |
734 Args: | 735 Args: |
735 command: String indicating the command that was received to trigger | 736 command: String indicating the command that was received to trigger |
736 this function. | 737 this function. |
737 options: optparse options dictionary. unused. | 738 options: optparse options dictionary. |
738 args: List of extra args from optparse. | 739 args: List of extra args from optparse. |
739 option_parser: optparse.OptionParser object. | 740 option_parser: optparse.OptionParser object. |
740 | 741 |
741 Returns: | 742 Returns: |
742 Integer indicated exit code. | 743 Integer indicated exit code. |
743 """ | 744 """ |
744 # If we don't have any args, display overall help | 745 # If we don't have any args, display overall help |
745 if len(args) < 3: | 746 if len(args) < 3: |
746 option_parser.print_help() | 747 option_parser.print_help() |
747 return 0 | 748 return 0 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 'monkey': CommandFunctionTuple( | 784 'monkey': CommandFunctionTuple( |
784 AddMonkeyTestOptions, RunTestsCommand), | 785 AddMonkeyTestOptions, RunTestsCommand), |
785 'perf': CommandFunctionTuple( | 786 'perf': CommandFunctionTuple( |
786 AddPerfTestOptions, RunTestsCommand), | 787 AddPerfTestOptions, RunTestsCommand), |
787 'linker': CommandFunctionTuple( | 788 'linker': CommandFunctionTuple( |
788 AddLinkerTestOptions, RunTestsCommand), | 789 AddLinkerTestOptions, RunTestsCommand), |
789 'help': CommandFunctionTuple(lambda option_parser: None, HelpCommand) | 790 'help': CommandFunctionTuple(lambda option_parser: None, HelpCommand) |
790 } | 791 } |
791 | 792 |
792 | 793 |
793 def DumpThreadStacks(_signal, _frame): | 794 def DumpThreadStacks(signal, frame): |
794 for thread in threading.enumerate(): | 795 for thread in threading.enumerate(): |
795 reraiser_thread.LogThreadStack(thread) | 796 reraiser_thread.LogThreadStack(thread) |
796 | 797 |
797 | 798 |
798 def main(): | 799 def main(argv): |
799 signal.signal(signal.SIGUSR1, DumpThreadStacks) | 800 signal.signal(signal.SIGUSR1, DumpThreadStacks) |
800 option_parser = command_option_parser.CommandOptionParser( | 801 option_parser = command_option_parser.CommandOptionParser( |
801 commands_dict=VALID_COMMANDS) | 802 commands_dict=VALID_COMMANDS) |
802 return command_option_parser.ParseAndExecute(option_parser) | 803 return command_option_parser.ParseAndExecute(option_parser) |
803 | 804 |
804 | 805 |
805 if __name__ == '__main__': | 806 if __name__ == '__main__': |
806 sys.exit(main()) | 807 sys.exit(main(sys.argv)) |
OLD | NEW |