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 |