diff options
author | nsylvain@google.com <nsylvain@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-14 17:41:49 +0000 |
---|---|---|
committer | nsylvain@google.com <nsylvain@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-14 17:41:49 +0000 |
commit | 96c09dee476cb1c44f0f39781ccc01879a9dd48a (patch) | |
tree | 3cc5abadb0899cdd00ca4f35a4d211be4387f41f /tools/sharding_supervisor | |
parent | 55421547b98a5f6ab2e3b28348abd25b21e1968a (diff) | |
download | chromium_src-96c09dee476cb1c44f0f39781ccc01879a9dd48a.zip chromium_src-96c09dee476cb1c44f0f39781ccc01879a9dd48a.tar.gz chromium_src-96c09dee476cb1c44f0f39781ccc01879a9dd48a.tar.bz2 |
Modify the sharding_supervisor to understand gtest's xml output.
We need to be able to merge it back into one final xml file if we
want the flakiness dashboard to work.
Review URL: https://chromiumcodereview.appspot.com/10082014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132342 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/sharding_supervisor')
-rwxr-xr-x | tools/sharding_supervisor/sharding_supervisor.py | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/tools/sharding_supervisor/sharding_supervisor.py b/tools/sharding_supervisor/sharding_supervisor.py index 077151e..035950e 100755 --- a/tools/sharding_supervisor/sharding_supervisor.py +++ b/tools/sharding_supervisor/sharding_supervisor.py @@ -24,6 +24,8 @@ import re import sys import threading +from xml.dom import minidom + # Add tools/ to path BASE_PATH = os.path.dirname(os.path.abspath(__file__)) sys.path.append(os.path.join(BASE_PATH, "..")) @@ -66,6 +68,79 @@ def DetectNumCores(): return SS_DEFAULT_NUM_CORES +def GetGTestOutput(args): + """Extracts gtest_output from the args. Returns none if not present.""" + + for arg in args: + if '--gtest_output=' in arg: + return arg.split('=')[1] + return None + + +def AppendToGTestOutput(gtest_args, value): + args = gtest_args[:] + current_value = GetGTestOutput(args) + if not current_value: + return + + current_arg = '--gtest_output=' + current_value + args.remove(current_arg) + args.append('--gtest_output=' + current_value + value) + return args + + +def RemoveGTestOutput(gtest_args): + args = gtest_args[:] + current_value = GetGTestOutput(args) + if not current_value: + return + + args.remove('--gtest_output=' + current_value) + return args + + +def AppendToXML(final_xml, generic_path, shard): + """Combine the shard xml file with the final xml file.""" + + path = generic_path + str(shard) + with open(path) as shard_xml_file: + shard_xml = minidom.parse(shard_xml_file) + + if not final_xml: + # Out final xml is empty, let's prepopulate it with the first one we see. + return shard_xml + + shard_node = shard_xml.documentElement + final_node = final_xml.documentElement + + testcases = shard_node.getElementsByTagName('testcase') + final_testcases = final_node.getElementsByTagName('testcase') + for testcase in testcases: + name = testcase.getAttribute('name') + classname = testcase.getAttribute('classname') + failures = testcase.getElementsByTagName('failure') + status = testcase.getAttribute('status') + elapsed = testcase.getAttribute('time') + + # don't bother updating the final xml if there is no data. + if status == 'notrun': + continue + + # Look in our final xml to see if it's there. + # There has to be a better way... + for final_testcase in final_testcases: + final_name = final_testcase.getAttribute('name') + final_classname = final_testcase.getAttribute('classname') + if final_name == name and final_classname == classname: + # We got the same entry. + final_testcase.setAttribute('status', status) + final_testcase.setAttribute('time', elapsed) + for failure in failures: + final_testcase.appendChild(failure) + + return final_xml + + def RunShard(test, total_shards, index, gtest_args, stdout, stderr): """Runs a single test shard in a subprocess. @@ -73,7 +148,10 @@ def RunShard(test, total_shards, index, gtest_args, stdout, stderr): The Popen object representing the subprocess handle. """ args = [test] - args.extend(gtest_args) + + # If there is a gtest_output + test_args = AppendToGTestOutput(gtest_args, str(index)) + args.extend(test_args) env = os.environ.copy() env["GTEST_TOTAL_SHARDS"] = str(total_shards) env["GTEST_SHARD_INDEX"] = str(index) @@ -282,6 +360,18 @@ class ShardingSupervisor(object): else: self.WaitForShards() + # All the shards are done. Merge all the XML files and generate the + # main one. + output_arg = GetGTestOutput(self.gtest_args) + if output_arg: + xml, xml_path = output_arg.split(':', 1) + assert(xml == 'xml') + final_xml = None + for i in range(start_point, start_point + self.num_shards_to_run): + final_xml = AppendToXML(final_xml, xml_path, i) + with open(xml_path, 'w') as final_file: + final_xml.writexml(final_file) + num_failed = len(self.failed_shards) if num_failed > 0: self.failed_shards.sort() @@ -391,7 +481,9 @@ class ShardingSupervisor(object): for test_filter in gtest_filters: args = [self.test, "--gtest_filter=" + test_filter] - args.extend(self.gtest_args) + # Don't update the xml output files during retry. + stripped_gtests_args = RemoveGTestOutput(self.gtest_args) + args.extend(stripped_gtests_args) rerun = subprocess.Popen(args) rerun.wait() if rerun.returncode != 0: |