Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: tools/sharding_supervisor/sharding_supervisor.py

Issue 10749018: Make merging of shard test results handle test suites that are split across shards better. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 116
117 if not final_xml: 117 if not final_xml:
118 # Out final xml is empty, let's prepopulate it with the first one we see. 118 # Out final xml is empty, let's prepopulate it with the first one we see.
119 return shard_xml 119 return shard_xml
120 120
121 shard_node = shard_xml.documentElement 121 shard_node = shard_xml.documentElement
122 final_node = final_xml.documentElement 122 final_node = final_xml.documentElement
123 123
124 testcases = shard_node.getElementsByTagName('testcase') 124 testcases = shard_node.getElementsByTagName('testcase')
125 final_testcases = final_node.getElementsByTagName('testcase') 125 final_testcases = final_node.getElementsByTagName('testcase')
126
127 final_testsuites = final_node.getElementsByTagName('testsuite')
128 final_testsuites_by_name = {}
129 for final_testsuite in final_testsuites:
130 final_testsuites_by_name[final_testsuite.getAttribute('name')] = \
M-A Ruel 2012/07/10 14:26:50 final_testsuites_by_name = dict( (suite.getAttri
Mihai Parparita -not on Chrome 2012/07/10 20:15:16 Done.
131 final_testsuite
132
126 for testcase in testcases: 133 for testcase in testcases:
127 name = testcase.getAttribute('name') 134 name = testcase.getAttribute('name')
128 classname = testcase.getAttribute('classname') 135 classname = testcase.getAttribute('classname')
129 failures = testcase.getElementsByTagName('failure') 136 failures = testcase.getElementsByTagName('failure')
130 status = testcase.getAttribute('status') 137 status = testcase.getAttribute('status')
131 elapsed = testcase.getAttribute('time') 138 elapsed = testcase.getAttribute('time')
132 139
133 # don't bother updating the final xml if there is no data. 140 # don't bother updating the final xml if there is no data.
134 if status == 'notrun': 141 if status == 'notrun':
135 continue 142 continue
136 143
137 # Look in our final xml to see if it's there. 144 # Look in our final xml to see if it's there.
138 # There has to be a better way... 145 # There has to be a better way...
146 merged_into_final_testcase = False
139 for final_testcase in final_testcases: 147 for final_testcase in final_testcases:
140 final_name = final_testcase.getAttribute('name') 148 final_name = final_testcase.getAttribute('name')
141 final_classname = final_testcase.getAttribute('classname') 149 final_classname = final_testcase.getAttribute('classname')
142 if final_name == name and final_classname == classname: 150 if final_name == name and final_classname == classname:
143 # We got the same entry. 151 # We got the same entry.
144 final_testcase.setAttribute('status', status) 152 final_testcase.setAttribute('status', status)
145 final_testcase.setAttribute('time', elapsed) 153 final_testcase.setAttribute('time', elapsed)
146 for failure in failures: 154 for failure in failures:
147 final_testcase.appendChild(failure) 155 final_testcase.appendChild(failure)
156 merged_into_final_testcase = True
157
158 # We couldn't find an existing testcase to merge the results into, so we
159 # copy the node into the existing test suite.
160 if not merged_into_final_testcase:
161 testsuite = testcase.parentNode
162 final_testsuite = final_testsuites_by_name[testsuite.getAttribute('name')]
nsylvain 2012/07/10 20:16:08 is it possible that the testsuite is not in the fi
Mihai Parparita -not on Chrome 2012/07/10 20:18:57 That didn't seem to be the case with the data that
163 final_testsuite.appendChild(testcase)
148 164
149 return final_xml 165 return final_xml
150 166
151 167
152 def RunShard(test, total_shards, index, gtest_args, stdout, stderr): 168 def RunShard(test, total_shards, index, gtest_args, stdout, stderr):
153 """Runs a single test shard in a subprocess. 169 """Runs a single test shard in a subprocess.
154 170
155 Returns: 171 Returns:
156 The Popen object representing the subprocess handle. 172 The Popen object representing the subprocess handle.
157 """ 173 """
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 shard_output: Buffer that stores the output from each shard. 297 shard_output: Buffer that stores the output from each shard.
282 test_counter: Stores the total number of tests run. 298 test_counter: Stores the total number of tests run.
283 total_slaves: Total number of slaves running this test. 299 total_slaves: Total number of slaves running this test.
284 slave_index: Current slave to run tests for. 300 slave_index: Current slave to run tests for.
285 301
286 If total_slaves is set, we run only a subset of the tests. This is meant to be 302 If total_slaves is set, we run only a subset of the tests. This is meant to be
287 used when we want to shard across machines as well as across cpus. In that 303 used when we want to shard across machines as well as across cpus. In that
288 case the number of shards to execute will be the same, but they will be 304 case the number of shards to execute will be the same, but they will be
289 smaller, as the total number of shards in the test suite will be multiplied 305 smaller, as the total number of shards in the test suite will be multiplied
290 by 'total_slaves'. 306 by 'total_slaves'.
291 307
292 For example, if you are on a quad core machine, the sharding supervisor by 308 For example, if you are on a quad core machine, the sharding supervisor by
293 default will use 20 shards for the whole suite. However, if you set 309 default will use 20 shards for the whole suite. However, if you set
294 total_slaves to 2, it will split the suite in 40 shards and will only run 310 total_slaves to 2, it will split the suite in 40 shards and will only run
295 shards [0-19] or shards [20-39] depending if you set slave_index to 0 or 1. 311 shards [0-19] or shards [20-39] depending if you set slave_index to 0 or 1.
296 """ 312 """
297 313
298 SHARD_COMPLETED = object() 314 SHARD_COMPLETED = object()
299 315
300 def __init__(self, test, num_shards_to_run, num_runs, color, original_order, 316 def __init__(self, test, num_shards_to_run, num_runs, color, original_order,
301 prefix, retry_percent, timeout, total_slaves, slave_index, 317 prefix, retry_percent, timeout, total_slaves, slave_index,
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 # shard and run the whole test 661 # shard and run the whole test
646 ss = ShardingSupervisor( 662 ss = ShardingSupervisor(
647 test, num_shards_to_run, num_runs, options.color, 663 test, num_shards_to_run, num_runs, options.color,
648 options.original_order, options.prefix, options.retry_percent, 664 options.original_order, options.prefix, options.retry_percent,
649 options.timeout, options.total_slaves, options.slave_index, gtest_args) 665 options.timeout, options.total_slaves, options.slave_index, gtest_args)
650 return ss.ShardTest() 666 return ss.ShardTest()
651 667
652 668
653 if __name__ == "__main__": 669 if __name__ == "__main__":
654 sys.exit(main()) 670 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698