| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Shards a given test suite and runs the shards in parallel. | 6 """Shards a given test suite and runs the shards in parallel. |
| 7 | 7 |
| 8 ShardingSupervisor is called to process the command line options and creates | 8 ShardingSupervisor is called to process the command line options and creates |
| 9 the specified number of worker threads. These threads then run each shard of | 9 the specified number of worker threads. These threads then run each shard of |
| 10 the test in a separate process and report on the results. When all the shards | 10 the test in a separate process and report on the results. When all the shards |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 if not current_value: | 86 if not current_value: |
| 87 return gtest_args | 87 return gtest_args |
| 88 | 88 |
| 89 current_arg = '--gtest_output=' + current_value | 89 current_arg = '--gtest_output=' + current_value |
| 90 args.remove(current_arg) | 90 args.remove(current_arg) |
| 91 args.append('--gtest_output=' + current_value + value) | 91 args.append('--gtest_output=' + current_value + value) |
| 92 return args | 92 return args |
| 93 | 93 |
| 94 | 94 |
| 95 def RemoveGTestOutput(gtest_args): | 95 def RemoveGTestOutput(gtest_args): |
| 96 args = gtest_args[:] | 96 return FilterArgs(gtest_args, '--gtest_output='); |
| 97 current_value = GetGTestOutput(args) | |
| 98 if not current_value: | |
| 99 return gtest_args | |
| 100 | 97 |
| 101 args.remove('--gtest_output=' + current_value) | 98 def FilterArgs(args, arg_filter): |
| 102 return args | 99 """Removes all strings in a list that don't start with |arg_filter|. |
| 100 |
| 101 Returns: |
| 102 A new, filtered list. |
| 103 """ |
| 104 filtered_args = [] |
| 105 for arg in args: |
| 106 if not arg.startswith(arg_filter): |
| 107 filtered_args.append(arg) |
| 108 return filtered_args |
| 103 | 109 |
| 104 | 110 |
| 105 def AppendToXML(final_xml, generic_path, shard): | 111 def AppendToXML(final_xml, generic_path, shard): |
| 106 """Combine the shard xml file with the final xml file.""" | 112 """Combine the shard xml file with the final xml file.""" |
| 107 | 113 |
| 108 path = generic_path + str(shard) | 114 path = generic_path + str(shard) |
| 109 | 115 |
| 110 try: | 116 try: |
| 111 with open(path) as shard_xml_file: | 117 with open(path) as shard_xml_file: |
| 112 shard_xml = minidom.parse(shard_xml_file) | 118 shard_xml = minidom.parse(shard_xml_file) |
| (...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 num_cores = DetectNumCores() | 596 num_cores = DetectNumCores() |
| 591 | 597 |
| 592 if options.shards_per_core < 1: | 598 if options.shards_per_core < 1: |
| 593 parser.error("You must have at least 1 shard per core!") | 599 parser.error("You must have at least 1 shard per core!") |
| 594 num_shards_to_run = num_cores * options.shards_per_core | 600 num_shards_to_run = num_cores * options.shards_per_core |
| 595 | 601 |
| 596 if options.runs_per_core < 1: | 602 if options.runs_per_core < 1: |
| 597 parser.error("You must have at least 1 run per core!") | 603 parser.error("You must have at least 1 run per core!") |
| 598 num_runs = num_cores * options.runs_per_core | 604 num_runs = num_cores * options.runs_per_core |
| 599 | 605 |
| 606 test = args[0] |
| 600 gtest_args = ["--gtest_color=%s" % { | 607 gtest_args = ["--gtest_color=%s" % { |
| 601 True: "yes", False: "no"}[options.color]] + args[1:] | 608 True: "yes", False: "no"}[options.color]] + args[1:] |
| 602 | 609 |
| 603 if options.original_order: | 610 if options.original_order: |
| 604 options.prefix = True | 611 options.prefix = True |
| 605 | 612 |
| 606 # TODO(charleslee): for backwards compatibility with buildbot's log_parser | 613 # TODO(charleslee): for backwards compatibility with buildbot's log_parser |
| 607 if options.reorder: | 614 if options.reorder: |
| 608 options.original_order = False | 615 options.original_order = False |
| 609 options.prefix = True | 616 options.prefix = True |
| 610 | 617 |
| 611 if options.random_seed: | 618 if options.random_seed: |
| 612 seed = random.randint(1, 99999) | 619 seed = random.randint(1, 99999) |
| 613 gtest_args.extend(["--gtest_shuffle", "--gtest_random_seed=%i" % seed]) | 620 gtest_args.extend(["--gtest_shuffle", "--gtest_random_seed=%i" % seed]) |
| 614 | 621 |
| 615 if options.retry_failed: | 622 if options.retry_failed: |
| 616 if options.retry_percent < 0 or options.retry_percent > 100: | 623 if options.retry_percent < 0 or options.retry_percent > 100: |
| 617 parser.error("Retry percent must be an integer [0, 100]!") | 624 parser.error("Retry percent must be an integer [0, 100]!") |
| 618 else: | 625 else: |
| 619 options.retry_percent = -1 | 626 options.retry_percent = -1 |
| 620 | 627 |
| 621 if options.runshard != None: | 628 if options.runshard != None: |
| 622 # run a single shard and exit | 629 # run a single shard and exit |
| 623 if (options.runshard < 0 or options.runshard >= num_shards_to_run): | 630 if (options.runshard < 0 or options.runshard >= num_shards_to_run): |
| 624 parser.error("Invalid shard number given parameters!") | 631 parser.error("Invalid shard number given parameters!") |
| 625 shard = RunShard( | 632 shard = RunShard( |
| 626 args[0], num_shards_to_run, options.runshard, gtest_args, None, None) | 633 test, num_shards_to_run, options.runshard, gtest_args, None, None) |
| 627 shard.communicate() | 634 shard.communicate() |
| 628 return shard.poll() | 635 return shard.poll() |
| 629 | 636 |
| 637 # When running browser_tests, run InProcessBrowserTest.Empty with a longer |
| 638 # timeout before running shards. This is needed to prevent timeouts on the |
| 639 # first run tests on Windows XP. See: http://crbug.com/124260 |
| 640 if test.find("browser_tests") > -1: |
| 641 args = [test] |
| 642 args.extend(gtest_args) |
| 643 args = FilterArgs(args, "--gtest_filter="); |
| 644 args = FilterArgs(args, "--ui-test-action-max-timeout="); |
| 645 args.append("--gtest_filter=InProcessBrowserTest.Empty"); |
| 646 args.append("--ui-test-action-max-timeout=240000"); |
| 647 result = subprocess.call(args, |
| 648 bufsize=0, |
| 649 universal_newlines=True) |
| 650 # If the test fails, don't run anything else. |
| 651 if result != 0: |
| 652 return 1 |
| 653 |
| 630 # shard and run the whole test | 654 # shard and run the whole test |
| 631 ss = ShardingSupervisor( | 655 ss = ShardingSupervisor( |
| 632 args[0], num_shards_to_run, num_runs, options.color, | 656 test, num_shards_to_run, num_runs, options.color, |
| 633 options.original_order, options.prefix, options.retry_percent, | 657 options.original_order, options.prefix, options.retry_percent, |
| 634 options.timeout, options.total_slaves, options.slave_index, gtest_args) | 658 options.timeout, options.total_slaves, options.slave_index, gtest_args) |
| 635 return ss.ShardTest() | 659 return ss.ShardTest() |
| 636 | 660 |
| 637 | 661 |
| 638 if __name__ == "__main__": | 662 if __name__ == "__main__": |
| 639 sys.exit(main()) | 663 sys.exit(main()) |
| OLD | NEW |