OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 24 matching lines...) Expand all Loading... | |
35 except ImportError: | 35 except ImportError: |
36 # Unable to find depot_tools, so just use standard subprocess | 36 # Unable to find depot_tools, so just use standard subprocess |
37 import subprocess | 37 import subprocess |
38 | 38 |
39 SS_USAGE = "python %prog [options] path/to/test [gtest_args]" | 39 SS_USAGE = "python %prog [options] path/to/test [gtest_args]" |
40 SS_DEFAULT_NUM_CORES = 4 | 40 SS_DEFAULT_NUM_CORES = 4 |
41 SS_DEFAULT_SHARDS_PER_CORE = 5 # num_shards = cores * SHARDS_PER_CORE | 41 SS_DEFAULT_SHARDS_PER_CORE = 5 # num_shards = cores * SHARDS_PER_CORE |
42 SS_DEFAULT_RUNS_PER_CORE = 1 # num_workers = cores * RUNS_PER_CORE | 42 SS_DEFAULT_RUNS_PER_CORE = 1 # num_workers = cores * RUNS_PER_CORE |
43 SS_DEFAULT_RETRY_PERCENT = 5 # --retry-failed ignored if more than 5% fail | 43 SS_DEFAULT_RETRY_PERCENT = 5 # --retry-failed ignored if more than 5% fail |
44 SS_DEFAULT_TIMEOUT = 530 # Slightly less than buildbot's default 600 seconds | 44 SS_DEFAULT_TIMEOUT = 530 # Slightly less than buildbot's default 600 seconds |
45 SS_DEFAULT_TOTAL_SLAVES = 1 # run the whole suite. | |
cmp
2012/04/05 19:07:49
yes!
| |
46 SS_DEFAULT_SLAVE_INDEX = 0 # run the tests for the first slave. | |
45 | 47 |
46 | 48 |
47 def DetectNumCores(): | 49 def DetectNumCores(): |
48 """Detects the number of cores on the machine. | 50 """Detects the number of cores on the machine. |
49 | 51 |
50 Returns: | 52 Returns: |
51 The number of cores on the machine or DEFAULT_NUM_CORES if it could not | 53 The number of cores on the machine or DEFAULT_NUM_CORES if it could not |
52 be found. | 54 be found. |
53 """ | 55 """ |
54 try: | 56 try: |
55 # Linux, Unix, MacOS | 57 # Linux, Unix, MacOS |
56 if hasattr(os, "sysconf"): | 58 if hasattr(os, "sysconf"): |
57 if "SC_NPROCESSORS_ONLN" in os.sysconf_names: | 59 if "SC_NPROCESSORS_ONLN" in os.sysconf_names: |
58 # Linux, Unix | 60 # Linux, Unix |
59 return int(os.sysconf("SC_NPROCESSORS_ONLN")) | 61 return int(os.sysconf("SC_NPROCESSORS_ONLN")) |
60 else: | 62 else: |
61 # OSX | 63 # OSX |
62 return int(os.popen2("sysctl -n hw.ncpu")[1].read()) | 64 return int(os.popen2("sysctl -n hw.ncpu")[1].read()) |
63 # Windows | 65 # Windows |
64 return int(os.environ["NUMBER_OF_PROCESSORS"]) | 66 return int(os.environ["NUMBER_OF_PROCESSORS"]) |
65 except ValueError: | 67 except ValueError: |
66 return SS_DEFAULT_NUM_CORES | 68 return SS_DEFAULT_NUM_CORES |
67 | 69 |
68 | 70 |
69 def RunShard(test, num_shards, index, gtest_args, stdout, stderr): | 71 def RunShard(test, total_shards, index, gtest_args, stdout, stderr): |
cmp
2012/04/05 19:07:49
thank you!
| |
70 """Runs a single test shard in a subprocess. | 72 """Runs a single test shard in a subprocess. |
71 | 73 |
72 Returns: | 74 Returns: |
73 The Popen object representing the subprocess handle. | 75 The Popen object representing the subprocess handle. |
74 """ | 76 """ |
75 args = [test] | 77 args = [test] |
76 args.extend(gtest_args) | 78 args.extend(gtest_args) |
77 env = os.environ.copy() | 79 env = os.environ.copy() |
78 env["GTEST_TOTAL_SHARDS"] = str(num_shards) | 80 env["GTEST_TOTAL_SHARDS"] = str(total_shards) |
79 env["GTEST_SHARD_INDEX"] = str(index) | 81 env["GTEST_SHARD_INDEX"] = str(index) |
80 | 82 |
81 # Use a unique log file for each shard | 83 # Use a unique log file for each shard |
82 # Allows ui_tests to be run in parallel on the same machine | 84 # Allows ui_tests to be run in parallel on the same machine |
83 env["CHROME_LOG_FILE"] = "chrome_log_%d" % index | 85 env["CHROME_LOG_FILE"] = "chrome_log_%d" % index |
84 | 86 |
85 return subprocess.Popen( | 87 return subprocess.Popen( |
86 args, stdout=stdout, | 88 args, stdout=stdout, |
87 stderr=stderr, | 89 stderr=stderr, |
88 env=env, | 90 env=env, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
148 as it is finished. | 150 as it is finished. |
149 """ | 151 """ |
150 while True: | 152 while True: |
151 try: | 153 try: |
152 index = self.counter.get_nowait() | 154 index = self.counter.get_nowait() |
153 except Queue.Empty: | 155 except Queue.Empty: |
154 break | 156 break |
155 chars = cStringIO.StringIO() | 157 chars = cStringIO.StringIO() |
156 shard_running = True | 158 shard_running = True |
157 shard = RunShard( | 159 shard = RunShard( |
158 self.supervisor.test, self.supervisor.num_shards, index, | 160 self.supervisor.test, self.supervisor.total_shards, index, |
159 self.supervisor.gtest_args, subprocess.PIPE, subprocess.STDOUT) | 161 self.supervisor.gtest_args, subprocess.PIPE, subprocess.STDOUT) |
160 while shard_running: | 162 while shard_running: |
161 char = shard.stdout.read(1) | 163 char = shard.stdout.read(1) |
162 if not char and shard.poll() is not None: | 164 if not char and shard.poll() is not None: |
163 shard_running = False | 165 shard_running = False |
164 chars.write(char) | 166 chars.write(char) |
165 if char == "\n" or not shard_running: | 167 if char == "\n" or not shard_running: |
166 line = chars.getvalue() | 168 line = chars.getvalue() |
167 if not line and not shard_running: | 169 if not line and not shard_running: |
168 break | 170 break |
169 self.ProcessLine(index, line) | 171 self.ProcessLine(index, line) |
170 self.supervisor.LogOutputLine(index, line) | 172 self.supervisor.LogOutputLine(index, line) |
171 chars.close() | 173 chars.close() |
172 chars = cStringIO.StringIO() | 174 chars = cStringIO.StringIO() |
173 if self.current_test: | 175 if self.current_test: |
174 self.ReportFailure("INCOMPLETE", index, self.current_test) | 176 self.ReportFailure("INCOMPLETE", index, self.current_test) |
175 self.supervisor.ShardIndexCompleted(index) | 177 self.supervisor.ShardIndexCompleted(index) |
176 if shard.returncode != 0: | 178 if shard.returncode != 0: |
177 self.supervisor.LogShardFailure(index) | 179 self.supervisor.LogShardFailure(index) |
178 | 180 |
179 | 181 |
180 class ShardingSupervisor(object): | 182 class ShardingSupervisor(object): |
181 """Supervisor object that handles the worker threads. | 183 """Supervisor object that handles the worker threads. |
182 | 184 |
183 Attributes: | 185 Attributes: |
184 test: Name of the test to shard. | 186 test: Name of the test to shard. |
185 num_shards: Total number of shards to split the test into. | 187 num_shards_to_run: Total number of shards to split the test into. |
186 num_runs: Total number of worker threads to create for running shards. | 188 num_runs: Total number of worker threads to create for running shards. |
187 color: Indicates which coloring mode to use in the output. | 189 color: Indicates which coloring mode to use in the output. |
188 original_order: True if shard output should be printed as it comes. | 190 original_order: True if shard output should be printed as it comes. |
189 prefix: True if each line should indicate the shard index. | 191 prefix: True if each line should indicate the shard index. |
190 retry_percent: Integer specifying the max percent of tests to retry. | 192 retry_percent: Integer specifying the max percent of tests to retry. |
191 gtest_args: The options to pass to gtest. | 193 gtest_args: The options to pass to gtest. |
192 failed_tests: List of statements from shard output indicating a failure. | 194 failed_tests: List of statements from shard output indicating a failure. |
193 failed_shards: List of shards that contained failing tests. | 195 failed_shards: List of shards that contained failing tests. |
194 shards_completed: List of flags indicating which shards have finished. | 196 shards_completed: List of flags indicating which shards have finished. |
195 shard_output: Buffer that stores the output from each shard. | 197 shard_output: Buffer that stores the output from each shard. |
196 test_counter: Stores the total number of tests run. | 198 test_counter: Stores the total number of tests run. |
199 total_slaves: Total number of slaves running this test. | |
200 slave_index: Current slave to run tests for. | |
201 | |
202 If total_slaves is set, we run only a subset of the tests. This is meant to be | |
203 used when we want to shard across machines as well as across cpus. In that | |
204 case the number of shards to execute will be the same, but they will be | |
205 smaller, as the total number of shards in the test suite will be multiplied | |
206 by 'total_slaves'. | |
207 | |
208 For example, if you are on a quad core machine, the sharding supervisor by | |
209 default will use 20 shards for the whole suite. However, if you set | |
210 total_slaves to 2, it will split the suite in 40 shards and will only run | |
211 shards [0-19] or shards [20-39] depending if you set slave_index to 0 or 1. | |
cmp
2012/04/05 19:07:49
will help a lot, thanks
| |
197 """ | 212 """ |
198 | 213 |
199 SHARD_COMPLETED = object() | 214 SHARD_COMPLETED = object() |
200 | 215 |
201 def __init__(self, test, num_shards, num_runs, color, original_order, | 216 def __init__(self, test, num_shards_to_run, num_runs, color, original_order, |
202 prefix, retry_percent, timeout, gtest_args): | 217 prefix, retry_percent, timeout, total_slaves, slave_index, |
218 gtest_args): | |
203 """Inits ShardingSupervisor with given options and gtest arguments.""" | 219 """Inits ShardingSupervisor with given options and gtest arguments.""" |
204 self.test = test | 220 self.test = test |
205 self.num_shards = num_shards | 221 # Number of shards to run locally. |
222 self.num_shards_to_run = num_shards_to_run | |
223 # Total shards in the test suite running across all slaves. | |
224 self.total_shards = num_shards_to_run * total_slaves | |
225 self.slave_index = slave_index | |
206 self.num_runs = num_runs | 226 self.num_runs = num_runs |
207 self.color = color | 227 self.color = color |
208 self.original_order = original_order | 228 self.original_order = original_order |
209 self.prefix = prefix | 229 self.prefix = prefix |
210 self.retry_percent = retry_percent | 230 self.retry_percent = retry_percent |
211 self.timeout = timeout | 231 self.timeout = timeout |
212 self.gtest_args = gtest_args | 232 self.gtest_args = gtest_args |
213 self.failed_tests = [] | 233 self.failed_tests = [] |
214 self.failed_shards = [] | 234 self.failed_shards = [] |
215 self.shards_completed = [False] * num_shards | 235 self.shards_completed = [False] * self.num_shards_to_run |
216 self.shard_output = [Queue.Queue() for _ in range(num_shards)] | 236 self.shard_output = [Queue.Queue() for _ in range(self.num_shards_to_run)] |
217 self.test_counter = itertools.count() | 237 self.test_counter = itertools.count() |
218 | 238 |
219 def ShardTest(self): | 239 def ShardTest(self): |
220 """Runs the test and manages the worker threads. | 240 """Runs the test and manages the worker threads. |
221 | 241 |
222 Runs the test and outputs a summary at the end. All the tests in the | 242 Runs the test and outputs a summary at the end. All the tests in the |
223 suite are run by creating (cores * runs_per_core) threads and | 243 suite are run by creating (cores * runs_per_core) threads and |
224 (cores * shards_per_core) shards. When all the worker threads have | 244 (cores * shards_per_core) shards. When all the worker threads have |
225 finished, the lines saved in failed_tests are printed again. If enabled, | 245 finished, the lines saved in failed_tests are printed again. If enabled, |
226 and failed tests that do not have FLAKY or FAILS in their names are run | 246 and failed tests that do not have FLAKY or FAILS in their names are run |
(...skipping 15 matching lines...) Expand all Loading... | |
242 | 262 |
243 test_start = re.compile( | 263 test_start = re.compile( |
244 ansi_regex + r"\[\s+RUN\s+\] " + ansi_regex + test_name_regex) | 264 ansi_regex + r"\[\s+RUN\s+\] " + ansi_regex + test_name_regex) |
245 test_ok = re.compile( | 265 test_ok = re.compile( |
246 ansi_regex + r"\[\s+OK\s+\] " + ansi_regex + test_name_regex) | 266 ansi_regex + r"\[\s+OK\s+\] " + ansi_regex + test_name_regex) |
247 test_fail = re.compile( | 267 test_fail = re.compile( |
248 ansi_regex + r"\[\s+FAILED\s+\] " + ansi_regex + test_name_regex) | 268 ansi_regex + r"\[\s+FAILED\s+\] " + ansi_regex + test_name_regex) |
249 | 269 |
250 workers = [] | 270 workers = [] |
251 counter = Queue.Queue() | 271 counter = Queue.Queue() |
252 for i in range(self.num_shards): | 272 start_point = self.num_shards_to_run * self.slave_index |
273 for i in range(start_point, start_point + self.num_shards_to_run): | |
253 counter.put(i) | 274 counter.put(i) |
254 | 275 |
255 for i in range(self.num_runs): | 276 for i in range(self.num_runs): |
256 worker = ShardRunner( | 277 worker = ShardRunner( |
257 self, counter, test_start, test_ok, test_fail) | 278 self, counter, test_start, test_ok, test_fail) |
258 worker.start() | 279 worker.start() |
259 workers.append(worker) | 280 workers.append(worker) |
260 if self.original_order: | 281 if self.original_order: |
261 for worker in workers: | 282 for worker in workers: |
262 worker.join() | 283 worker.join() |
(...skipping 25 matching lines...) Expand all Loading... | |
288 | 309 |
289 def LogShardFailure(self, index): | 310 def LogShardFailure(self, index): |
290 """Records that a test in the given shard has failed.""" | 311 """Records that a test in the given shard has failed.""" |
291 self.failed_shards.append(index) | 312 self.failed_shards.append(index) |
292 | 313 |
293 def WaitForShards(self): | 314 def WaitForShards(self): |
294 """Prints the output from each shard in consecutive order, waiting for | 315 """Prints the output from each shard in consecutive order, waiting for |
295 the current shard to finish before starting on the next shard. | 316 the current shard to finish before starting on the next shard. |
296 """ | 317 """ |
297 try: | 318 try: |
298 for shard_index in range(self.num_shards): | 319 for shard_index in range(self.num_shards_to_run): |
299 while True: | 320 while True: |
300 try: | 321 try: |
301 line = self.shard_output[shard_index].get(True, self.timeout) | 322 line = self.shard_output[shard_index].get(True, self.timeout) |
302 except Queue.Empty: | 323 except Queue.Empty: |
303 # Shard timed out, notice failure and move on. | 324 # Shard timed out, notice failure and move on. |
304 self.LogShardFailure(shard_index) | 325 self.LogShardFailure(shard_index) |
305 # TODO(maruel): Print last test. It'd be simpler to have the | 326 # TODO(maruel): Print last test. It'd be simpler to have the |
306 # processing in the main thread. | 327 # processing in the main thread. |
307 # TODO(maruel): Make sure the worker thread terminates. | 328 # TODO(maruel): Make sure the worker thread terminates. |
308 sys.stdout.write('TIMED OUT\n\n') | 329 sys.stdout.write('TIMED OUT\n\n') |
309 LogTestFailure( | 330 LogTestFailure( |
310 'FAILURE: SHARD %d TIMED OUT; %d seconds' % ( | 331 'FAILURE: SHARD %d TIMED OUT; %d seconds' % ( |
311 shard_index, self.timeout)) | 332 shard_index, self.timeout)) |
312 break | 333 break |
313 if line is self.SHARD_COMPLETED: | 334 if line is self.SHARD_COMPLETED: |
314 break | 335 break |
315 sys.stdout.write(line) | 336 sys.stdout.write(line) |
316 except: | 337 except: |
317 sys.stdout.flush() | 338 sys.stdout.flush() |
318 print >> sys.stderr, 'CAUGHT EXCEPTION: dumping remaining data:' | 339 print >> sys.stderr, 'CAUGHT EXCEPTION: dumping remaining data:' |
319 for shard_index in range(self.num_shards): | 340 for shard_index in range(self.num_shards_to_run): |
320 while True: | 341 while True: |
321 try: | 342 try: |
322 line = self.shard_output[shard_index].get(False) | 343 line = self.shard_output[shard_index].get(False) |
323 except Queue.Empty: | 344 except Queue.Empty: |
324 # Shard timed out, notice failure and move on. | 345 # Shard timed out, notice failure and move on. |
325 self.LogShardFailure(shard_index) | 346 self.LogShardFailure(shard_index) |
326 break | 347 break |
327 if line is self.SHARD_COMPLETED: | 348 if line is self.SHARD_COMPLETED: |
328 break | 349 break |
329 sys.stderr.write(line) | 350 sys.stderr.write(line) |
330 raise | 351 raise |
331 | 352 |
332 def LogOutputLine(self, index, line): | 353 def LogOutputLine(self, index, line): |
333 """Either prints the shard output line immediately or saves it in the | 354 """Either prints the shard output line immediately or saves it in the |
334 output buffer, depending on the settings. Also optionally adds a prefix. | 355 output buffer, depending on the settings. Also optionally adds a prefix. |
335 """ | 356 """ |
357 # Fix up the index. | |
358 array_index = index - (self.num_shards_to_run * self.slave_index) | |
336 if self.prefix: | 359 if self.prefix: |
337 line = "%i>%s" % (index, line) | 360 line = "%i>%s" % (index, line) |
338 if self.original_order: | 361 if self.original_order: |
339 sys.stdout.write(line) | 362 sys.stdout.write(line) |
340 else: | 363 else: |
341 self.shard_output[index].put(line) | 364 self.shard_output[array_index].put(line) |
342 | 365 |
343 def IncrementTestCount(self): | 366 def IncrementTestCount(self): |
344 """Increments the number of tests run. This is relevant to the | 367 """Increments the number of tests run. This is relevant to the |
345 --retry-percent option. | 368 --retry-percent option. |
346 """ | 369 """ |
347 self.test_counter.next() | 370 self.test_counter.next() |
348 | 371 |
349 def ShardIndexCompleted(self, index): | 372 def ShardIndexCompleted(self, index): |
350 """Records that a shard has finished so the output from the next shard | 373 """Records that a shard has finished so the output from the next shard |
351 can now be printed. | 374 can now be printed. |
352 """ | 375 """ |
353 self.shard_output[index].put(self.SHARD_COMPLETED) | 376 # Fix up the index. |
377 array_index = index - (self.num_shards_to_run * self.slave_index) | |
378 self.shard_output[array_index].put(self.SHARD_COMPLETED) | |
354 | 379 |
355 def RetryFailedTests(self): | 380 def RetryFailedTests(self): |
356 """Reruns any failed tests serially and prints another summary of the | 381 """Reruns any failed tests serially and prints another summary of the |
357 results if no more than retry_percent failed. | 382 results if no more than retry_percent failed. |
358 """ | 383 """ |
359 num_tests_run = self.test_counter.next() | 384 num_tests_run = self.test_counter.next() |
360 if len(self.failed_tests) > self.retry_percent * num_tests_run: | 385 if len(self.failed_tests) > self.retry_percent * num_tests_run: |
361 sys.stderr.write("\nNOT RETRYING FAILED TESTS (too many failed)\n") | 386 sys.stderr.write("\nNOT RETRYING FAILED TESTS (too many failed)\n") |
362 return 1 | 387 return 1 |
363 self.WriteText(sys.stderr, "\nRETRYING FAILED TESTS:\n", "\x1b[1;5;33m") | 388 self.WriteText(sys.stderr, "\nRETRYING FAILED TESTS:\n", "\x1b[1;5;33m") |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
440 "--retry-failed", action="store_true", | 465 "--retry-failed", action="store_true", |
441 help="retry tests that did not pass serially") | 466 help="retry tests that did not pass serially") |
442 parser.add_option( | 467 parser.add_option( |
443 "--retry-percent", type="int", | 468 "--retry-percent", type="int", |
444 default=SS_DEFAULT_RETRY_PERCENT, | 469 default=SS_DEFAULT_RETRY_PERCENT, |
445 help="ignore --retry-failed if more than this percent fail [0, 100]" | 470 help="ignore --retry-failed if more than this percent fail [0, 100]" |
446 " (default = %i)" % SS_DEFAULT_RETRY_PERCENT) | 471 " (default = %i)" % SS_DEFAULT_RETRY_PERCENT) |
447 parser.add_option( | 472 parser.add_option( |
448 "-t", "--timeout", type="int", default=SS_DEFAULT_TIMEOUT, | 473 "-t", "--timeout", type="int", default=SS_DEFAULT_TIMEOUT, |
449 help="timeout in seconds to wait for a shard (default=%default s)") | 474 help="timeout in seconds to wait for a shard (default=%default s)") |
475 parser.add_option( | |
476 "--total-slaves", type="int", default=SS_DEFAULT_TOTAL_SLAVES, | |
477 help="if running a subset, number of slaves sharing the test") | |
478 parser.add_option( | |
479 "--slave-index", type="int", default=SS_DEFAULT_SLAVE_INDEX, | |
480 help="if running a subset, index of the slave to run tests for") | |
481 | |
450 parser.disable_interspersed_args() | 482 parser.disable_interspersed_args() |
451 (options, args) = parser.parse_args() | 483 (options, args) = parser.parse_args() |
452 | 484 |
453 if not args: | 485 if not args: |
454 parser.error("You must specify a path to test!") | 486 parser.error("You must specify a path to test!") |
455 if not os.path.exists(args[0]): | 487 if not os.path.exists(args[0]): |
456 parser.error("%s does not exist!" % args[0]) | 488 parser.error("%s does not exist!" % args[0]) |
457 | 489 |
458 num_cores = DetectNumCores() | 490 num_cores = DetectNumCores() |
459 | 491 |
460 if options.shards_per_core < 1: | 492 if options.shards_per_core < 1: |
461 parser.error("You must have at least 1 shard per core!") | 493 parser.error("You must have at least 1 shard per core!") |
462 num_shards = num_cores * options.shards_per_core | 494 num_shards_to_run = num_cores * options.shards_per_core |
463 | 495 |
464 if options.runs_per_core < 1: | 496 if options.runs_per_core < 1: |
465 parser.error("You must have at least 1 run per core!") | 497 parser.error("You must have at least 1 run per core!") |
466 num_runs = num_cores * options.runs_per_core | 498 num_runs = num_cores * options.runs_per_core |
467 | 499 |
468 gtest_args = ["--gtest_color=%s" % { | 500 gtest_args = ["--gtest_color=%s" % { |
469 True: "yes", False: "no"}[options.color]] + args[1:] | 501 True: "yes", False: "no"}[options.color]] + args[1:] |
470 | 502 |
471 if options.original_order: | 503 if options.original_order: |
472 options.prefix = True | 504 options.prefix = True |
473 | 505 |
474 # TODO(charleslee): for backwards compatibility with buildbot's log_parser | 506 # TODO(charleslee): for backwards compatibility with buildbot's log_parser |
475 if options.reorder: | 507 if options.reorder: |
476 options.original_order = False | 508 options.original_order = False |
477 options.prefix = True | 509 options.prefix = True |
478 | 510 |
479 if options.random_seed: | 511 if options.random_seed: |
480 seed = random.randint(1, 99999) | 512 seed = random.randint(1, 99999) |
481 gtest_args.extend(["--gtest_shuffle", "--gtest_random_seed=%i" % seed]) | 513 gtest_args.extend(["--gtest_shuffle", "--gtest_random_seed=%i" % seed]) |
482 | 514 |
483 if options.retry_failed: | 515 if options.retry_failed: |
484 if options.retry_percent < 0 or options.retry_percent > 100: | 516 if options.retry_percent < 0 or options.retry_percent > 100: |
485 parser.error("Retry percent must be an integer [0, 100]!") | 517 parser.error("Retry percent must be an integer [0, 100]!") |
486 else: | 518 else: |
487 options.retry_percent = -1 | 519 options.retry_percent = -1 |
488 | 520 |
489 if options.runshard != None: | 521 if options.runshard != None: |
490 # run a single shard and exit | 522 # run a single shard and exit |
491 if (options.runshard < 0 or options.runshard >= num_shards): | 523 if (options.runshard < 0 or options.runshard >= num_shards_to_run): |
492 parser.error("Invalid shard number given parameters!") | 524 parser.error("Invalid shard number given parameters!") |
493 shard = RunShard( | 525 shard = RunShard( |
494 args[0], num_shards, options.runshard, gtest_args, None, None) | 526 args[0], num_shards_to_run, options.runshard, gtest_args, None, None) |
495 shard.communicate() | 527 shard.communicate() |
496 return shard.poll() | 528 return shard.poll() |
497 | 529 |
498 # shard and run the whole test | 530 # shard and run the whole test |
499 ss = ShardingSupervisor( | 531 ss = ShardingSupervisor( |
500 args[0], num_shards, num_runs, options.color, options.original_order, | 532 args[0], num_shards_to_run, num_runs, options.color, |
501 options.prefix, options.retry_percent, options.timeout, gtest_args) | 533 options.original_order, options.prefix, options.retry_percent, |
534 options.timeout, options.total_slaves, options.slave_index, gtest_args) | |
502 return ss.ShardTest() | 535 return ss.ShardTest() |
503 | 536 |
504 | 537 |
505 if __name__ == "__main__": | 538 if __name__ == "__main__": |
506 sys.exit(main()) | 539 sys.exit(main()) |
OLD | NEW |