Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
|
Paweł Hajdan Jr.
2011/08/19 18:35:50
Add a new directory for those like toos/flakiness.
clee
2011/08/19 21:06:35
Done.
| |
| 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 subprocess | |
| 17 import time | |
| 18 | |
| 19 | |
| 20 FF_USAGE = 'python %prog [options] path/to/test [sharding_supervisor_args]' | |
| 21 FF_DEFAULT_DATA_SUFFIX = '_flakies' | |
| 22 FF_DEFAULT_SLEEP_INTERVAL = 10.0 | |
| 23 FF_DEFAULT_NUM_ITERATIONS = 100 | |
| 24 FF_DEFAULT_SUPERVISOR_ARGS = ['-r3', '--random-seed'] | |
| 25 | |
| 26 | |
| 27 def FindFlakies(test_path, data_path, supervisor_args): | |
| 28 failed_tests = {} | |
| 29 # read a previously written data file | |
|
Paweł Hajdan Jr.
2011/08/19 18:35:50
nit: Comments should start with a capital letter a
clee
2011/08/19 21:06:35
Done.
| |
| 30 if os.path.exists(data_path): | |
| 31 data_file = open(data_path, 'r') | |
| 32 num_runs = int(data_file.readline().split(' ')[0]) | |
| 33 num_passes = int(data_file.readline().split(' ')[0]) | |
| 34 for line in data_file: | |
| 35 if line: | |
| 36 split_line = line.split(' -> ') | |
| 37 failed_tests[split_line[0]] = int(split_line[1]) | |
| 38 data_file.close() | |
| 39 # no data file found | |
| 40 else: | |
| 41 num_runs = 0 | |
| 42 num_passes = 0 | |
| 43 | |
| 44 log_lines = False | |
| 45 args = ['python', 'sharding_supervisor/sharding_supervisor.py'] | |
| 46 args.extend(supervisor_args + [test_path]) | |
| 47 proc = subprocess.Popen(args, stderr=subprocess.PIPE) | |
| 48 | |
| 49 # shard the test and collect failures | |
| 50 while True: | |
| 51 line = proc.stderr.readline() | |
| 52 if not line: | |
| 53 if proc.poll() is not None: | |
| 54 break | |
| 55 continue | |
| 56 print line.rstrip() | |
| 57 if log_lines: | |
| 58 line = line.rstrip() | |
| 59 if line in failed_tests: | |
| 60 failed_tests[line] += 1 | |
| 61 else: | |
| 62 failed_tests[line] = 1 | |
| 63 elif line.find('FAILED TESTS:') >= 0: | |
| 64 log_lines = True | |
| 65 num_runs += 1 | |
| 66 if proc.returncode == 0: | |
| 67 num_passes += 1 | |
| 68 | |
| 69 # write the data file and print results | |
| 70 data_file = open(data_path, 'w') | |
| 71 print '%i runs' % num_runs | |
| 72 data_file.write('%i runs\n' % num_runs) | |
| 73 print '%i passes' % num_passes | |
| 74 data_file.write('%i passes\n' % num_passes) | |
| 75 for (test, count) in failed_tests.iteritems(): | |
| 76 print '%s -> %i' % (test, count) | |
| 77 data_file.write('%s -> %i\n' % (test, count)) | |
| 78 data_file.close() | |
| 79 | |
| 80 | |
| 81 def main(): | |
| 82 parser = optparse.OptionParser(usage=FF_USAGE) | |
| 83 parser.add_option( | |
| 84 '--data-path', | |
| 85 help='path to i/o file (default is to append "%s" to the end of the' | |
| 86 ' test name in the current directory)' % FF_DEFAULT_DATA_SUFFIX) | |
| 87 parser.add_option( | |
| 88 '--sleep', type='float', default=FF_DEFAULT_SLEEP_INTERVAL, | |
| 89 help='sleep interval between each run, useful for overnight runs' | |
| 90 ' (default = %i)' % FF_DEFAULT_SLEEP_INTERVAL) | |
| 91 parser.add_option( | |
| 92 '--iterations', type='int', default=FF_DEFAULT_NUM_ITERATIONS, | |
| 93 help='number of times to run the sharded test' | |
| 94 ' (default = %i)' % FF_DEFAULT_NUM_ITERATIONS) | |
| 95 parser.disable_interspersed_args() | |
| 96 (options, args) = parser.parse_args() | |
| 97 | |
| 98 if not args: | |
| 99 parser.error('You must specify a path to test!') | |
| 100 if not os.path.exists(args[0]): | |
| 101 parser.error('%s does not exist!' % args[0]) | |
| 102 | |
| 103 if not options.data_path: | |
| 104 options.data_path = os.path.basename(args[0]) + FF_DEFAULT_DATA_SUFFIX | |
| 105 | |
| 106 supervisor_args = FF_DEFAULT_SUPERVISOR_ARGS + args[1:] | |
| 107 | |
| 108 for i in range(options.iterations): | |
| 109 FindFlakies(args[0], options.data_path, supervisor_args) | |
| 110 print 'That was just iteration %i of %i' % (i + 1, options.iterations) | |
| 111 time.sleep(options.sleep) | |
| 112 | |
| 113 | |
| 114 if __name__ == '__main__': | |
| 115 main() | |
| OLD | NEW |