OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 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 |
| 4 # found in the LICENSE file. |
| 5 |
| 6 """Finds flaky test cases by sharding and running a test for the specified |
| 7 number of times. The data file is read at the beginning of each run to find |
| 8 the last known counts and is overwritten at the end of each run with the new |
| 9 counts. There is an optional sleep interval between each run so the script can |
| 10 be killed without losing the data, useful for overnight (or weekend!) runs. |
| 11 """ |
| 12 |
| 13 |
| 14 import optparse |
| 15 import os |
| 16 import random |
| 17 import subprocess |
| 18 import sys |
| 19 import time |
| 20 |
| 21 |
| 22 FF_USAGE = 'python %prog [options] path/to/test [sharding_supervisor_args]' |
| 23 FF_DEFAULT_DATA_SUFFIX = '_flakies' |
| 24 FF_DEFAULT_SLEEP_INTERVAL = 10.0 |
| 25 FF_DEFAULT_NUM_ITERATIONS = 100 |
| 26 FF_DEFAULT_SUPERVISOR_ARGS = ['-r3', '--random-seed'] |
| 27 |
| 28 |
| 29 def FindFlakies(test_path, data_path, supervisor_args): |
| 30 failed_tests = {} |
| 31 if os.path.exists(data_path): |
| 32 data_file = open(data_path, 'r') |
| 33 num_runs = int(data_file.readline().split(' ')[0]) |
| 34 num_passes = int(data_file.readline().split(' ')[0]) |
| 35 for line in data_file: |
| 36 if line: |
| 37 split_line = line.split(' -> ') |
| 38 failed_tests[split_line[0]] = int(split_line[1]) |
| 39 data_file.close() |
| 40 else: |
| 41 num_runs = 0 |
| 42 num_passes = 0 |
| 43 log_lines = False |
| 44 args = ['python', 'sharding_supervisor/sharding_supervisor.py'] |
| 45 args.extend(supervisor_args + [test_path]) |
| 46 proc = subprocess.Popen(args, stderr=subprocess.PIPE) |
| 47 while True: |
| 48 line = proc.stderr.readline() |
| 49 if not line: |
| 50 if proc.poll() is not None: |
| 51 break |
| 52 continue |
| 53 sys.stderr.write(line) |
| 54 if log_lines: |
| 55 line = line.rstrip() |
| 56 if line in failed_tests: |
| 57 failed_tests[line] += 1 |
| 58 else: |
| 59 failed_tests[line] = 1 |
| 60 elif line.find('FAILED TESTS:') >= 0: |
| 61 log_lines = True |
| 62 num_runs += 1 |
| 63 if proc.returncode == 0: |
| 64 num_passes += 1 |
| 65 data_file = open(data_path, 'w') |
| 66 print '%i runs' % num_runs |
| 67 data_file.write('%i runs\n' % num_runs) |
| 68 print '%i passes' % num_passes |
| 69 data_file.write('%i passes\n' % num_passes) |
| 70 for (test, count) in failed_tests.iteritems(): |
| 71 print '%s -> %i' % (test, count) |
| 72 data_file.write('%s -> %i\n' % (test, count)) |
| 73 data_file.close() |
| 74 |
| 75 |
| 76 def main(): |
| 77 parser = optparse.OptionParser(usage=FF_USAGE) |
| 78 parser.add_option( |
| 79 '--data-path', |
| 80 help='path to i/o file (default is to append "%s" to the end of the' |
| 81 ' test name in the current directory)' % FF_DEFAULT_DATA_SUFFIX) |
| 82 parser.add_option( |
| 83 '--sleep', type='float', default=FF_DEFAULT_SLEEP_INTERVAL, |
| 84 help='sleep interval between each run, useful for overnight runs' |
| 85 ' (default = %i)' % FF_DEFAULT_SLEEP_INTERVAL) |
| 86 parser.add_option( |
| 87 '--iterations', type='int', default=FF_DEFAULT_NUM_ITERATIONS, |
| 88 help='number of times to run the sharded test' |
| 89 ' (default = %i)' % FF_DEFAULT_NUM_ITERATIONS) |
| 90 parser.disable_interspersed_args() |
| 91 (options, args) = parser.parse_args() |
| 92 |
| 93 if not args: |
| 94 parser.error('You must specify a path to test!') |
| 95 if not os.path.exists(args[0]): |
| 96 parser.error('%s does not exist!' % args[0]) |
| 97 |
| 98 if not options.data_path: |
| 99 options.data_path = os.path.basename(args[0]) + FF_DEFAULT_DATA_SUFFIX |
| 100 |
| 101 supervisor_args = FF_DEFAULT_SUPERVISOR_ARGS + args[1:] |
| 102 |
| 103 for i in range(options.iterations): |
| 104 FindFlakies(args[0], options.data_path, supervisor_args) |
| 105 print 'That was just iteration %i of %i' % (i + 1, options.iterations) |
| 106 time.sleep(options.sleep) |
| 107 |
| 108 |
| 109 if __name__ == '__main__': |
| 110 main() |
OLD | NEW |