2 # Copyright 2017 The Chromium Authors
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Runs all permutations of pairs of tests in a gtest binary to attempt to
7 detect state leakage between tests.
11 gn gen out/asan --args='is_asan=true enable_nacl=false is_debug=false'
12 ninja -C out/asan base_unittests
13 tools/perry.py out/asan/base_unittests > perry.log &
16 You might want to run it in `screen` as it'll take a while.
19 from __future__ import print_function
23 import multiprocessing
28 def _GetTestList(path_to_binary):
29 """Returns a set of full test names.
31 Each test will be of the form "Case.Test". There will be a separate line
32 for each combination of Case/Test (there are often multiple tests in each
35 raw_output = subprocess.check_output([path_to_binary, "--gtest_list_tests"])
36 input_lines = raw_output.splitlines()
38 # The format of the gtest_list_tests output is:
40 # " Test1 # <Optional extra stuff>"
44 case_name = '' # Includes trailing dot.
46 for line in input_lines:
49 line = line[:line.find('#')]
51 # Indented means a test in previous case.
52 test_set.add(case_name + line.strip())
55 case_name = line.strip()
60 def _CheckForFailure(data):
61 test_binary, pair0, pair1 = data
63 [test_binary, '--gtest_repeat=5', '--gtest_shuffle',
64 '--gtest_filter=' + pair0 + ':' + pair1],
65 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
66 out, _ = p.communicate()
68 return (pair0, pair1, out)
72 def _PrintStatus(i, total, failed):
73 status = '%d of %d tested (%d failures)' % (i+1, total, failed)
74 print('\r%s%s' % (status, '\x1B[K'), end=' ')
79 parser = argparse.ArgumentParser(description="Find failing pairs of tests.")
80 parser.add_argument('binary', help='Path to gtest binary or wrapper script.')
81 args = parser.parse_args()
82 print('Getting test list...')
83 all_tests = _GetTestList(args.binary)
84 permuted = [(args.binary, x, y) for x in all_tests for y in all_tests]
87 pool = multiprocessing.Pool()
88 total_count = len(permuted)
89 for i, result in enumerate(pool.imap_unordered(
90 _CheckForFailure, permuted, 1)):
92 print('\n--gtest_filter=%s:%s failed\n\n%s\n\n' % (result[0], result[1],
95 _PrintStatus(i, total_count, len(failed))
101 print('Failed pairs:')
108 if __name__ == '__main__':