OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright 2014 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 """A "smart" test runner for gtest unit tests (that caches successes).""" | |
7 | |
8 import logging | |
9 import os | |
10 import subprocess | |
11 import sys | |
12 | |
13 _logging = logging.getLogger() | |
14 | |
15 _script_dir = os.path.dirname(os.path.abspath(__file__)) | |
16 sys.path.insert(0, os.path.join(_script_dir, "pylib")) | |
17 | |
18 from transitive_hash import transitive_hash | |
19 | |
20 def main(argv): | |
21 logging.basicConfig() | |
22 # Uncomment to debug: | |
23 # _logging.setLevel(logging.DEBUG) | |
24 | |
25 if len(argv) < 3 or len(argv) > 4: | |
26 print "Usage: %s gtest_list_file root_dir [successes_cache_file]" % \ | |
27 os.path.basename(argv[0]) | |
28 return 0 if len(argv) < 2 else 1 | |
29 | |
30 _logging.debug("Test list file: %s", argv[1]) | |
31 with open(argv[1], 'rb') as f: | |
32 gtest_list = [y for y in [x.strip() for x in f.readlines()] \ | |
33 if y and y[0] != '#'] | |
34 _logging.debug("Test list: %s" % gtest_list) | |
35 | |
36 print "Running tests in directory: %s" % argv[2] | |
37 os.chdir(argv[2]) | |
38 | |
39 if len(argv) == 4 and argv[3]: | |
40 successes_cache_filename = argv[3] | |
41 print "Successes cache file: %s" % successes_cache_filename | |
42 else: | |
43 successes_cache_filename = None | |
44 print "No successes cache file (will run all tests unconditionally)" | |
45 | |
46 if successes_cache_filename: | |
47 # This file simply contains a list of transitive hashes of tests that | |
48 # succeeded. | |
49 try: | |
50 _logging.debug("Trying to read successes cache file: %s", | |
51 successes_cache_filename) | |
52 with open(argv[3], 'rb') as f: | |
53 successes = set([x.strip() for x in f.readlines()]) | |
54 _logging.debug("Successes: %s", successes) | |
55 except: | |
56 # Just assume that it didn't exist, or whatever. | |
57 print "Failed to read successes cache file %s (will create)" % argv[3] | |
58 successes = set() | |
59 | |
60 # Run gtests with color if we're on a TTY (and we're not being told explicitly | |
61 # what to do). | |
62 if sys.stdout.isatty() and 'GTEST_COLOR' not in os.environ: | |
63 _logging.debug("Setting GTEST_COLOR=yes") | |
64 os.environ['GTEST_COLOR'] = 'yes' | |
65 | |
66 # TODO(vtl): We may not close this file on failure. | |
67 successes_cache_file = open(successes_cache_filename, 'ab') \ | |
68 if successes_cache_filename else None | |
69 for gtest in gtest_list: | |
70 if gtest[0] == '*': | |
71 gtest = gtest[1:] | |
72 _logging.debug("%s is marked as non-cacheable" % gtest) | |
73 cacheable = False | |
74 else: | |
75 cacheable = True | |
76 | |
77 if successes_cache_file and cacheable: | |
78 _logging.debug("Getting transitive hash for %s ... " % gtest) | |
79 try: | |
80 gtest_hash = transitive_hash(gtest) | |
81 except: | |
82 print "Failed to get transitive hash for %s" % gtest | |
83 return 1 | |
84 _logging.debug(" Transitive hash: %s" % gtest_hash) | |
85 | |
86 if gtest_hash in successes: | |
87 print "Skipping %s (previously succeeded)" % gtest | |
88 continue | |
89 | |
90 print "Running %s...." % gtest, | |
91 sys.stdout.flush() | |
92 try: | |
93 subprocess.check_output(["./" + gtest], stderr=subprocess.STDOUT) | |
94 print "Succeeded" | |
95 # Record success. | |
96 if successes_cache_filename and cacheable: | |
97 successes.add(gtest_hash) | |
98 successes_cache_file.write(gtest_hash + '\n') | |
99 successes_cache_file.flush() | |
100 except subprocess.CalledProcessError as e: | |
101 print "Failed with exit code %d and output:" % e.returncode | |
102 print 72 * '-' | |
103 print e.output | |
104 print 72 * '-' | |
105 return 1 | |
106 except OSError as e: | |
107 print " Failed to start test" | |
108 return 1 | |
109 print "All tests succeeded" | |
110 if successes_cache_file: | |
111 successes_cache_file.close() | |
112 | |
113 return 0 | |
114 | |
115 if __name__ == '__main__': | |
116 sys.exit(main(sys.argv)) | |
OLD | NEW |