Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: swarm_client/googletest/trace_test_cases.py

Issue 69143004: Delete swarm_client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « swarm_client/googletest/tests/trace_test_cases_smoke_test.py ('k') | swarm_client/isolate.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2013 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 """Traces each test cases of a google-test executable individually.
7
8 Gives detailed information about each test case. The logs can be read afterward
9 with ./trace_inputs.py read -l /path/to/executable.logs
10 """
11
12 import logging
13 import multiprocessing
14 import os
15 import sys
16 import time
17
18 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
19 if not ROOT_DIR in sys.path:
20 sys.path.insert(0, ROOT_DIR)
21
22 import run_test_cases
23 import trace_inputs
24
25 from utils import threading_utils
26 from utils import tools
27
28
29 def sanitize_test_case_name(test_case):
30 """Removes characters that are valid as test case names but invalid as file
31 names.
32 """
33 return test_case.replace('/', '-')
34
35
36 class Tracer(object):
37 def __init__(self, tracer, cmd, cwd_dir, progress):
38 # Constants
39 self.tracer = tracer
40 self.cmd = cmd[:]
41 self.cwd_dir = cwd_dir
42 self.progress = progress
43
44 def map(self, test_case):
45 """Traces a single test case and returns its output."""
46 cmd = self.cmd[:]
47 cmd.append('--gtest_filter=%s' % test_case)
48 tracename = sanitize_test_case_name(test_case)
49
50 out = []
51 for retry in range(5):
52 start = time.time()
53 returncode, output = self.tracer.trace(cmd, self.cwd_dir, tracename, True)
54 duration = time.time() - start
55 # TODO(maruel): Define a way to detect if a strace log is valid.
56 valid = True
57 out.append(
58 {
59 'test_case': test_case,
60 'tracename': tracename,
61 'returncode': returncode,
62 'duration': duration,
63 'valid': valid,
64 'output': output,
65 })
66 logging.debug(
67 'Tracing %s done: %d, %.1fs' % (test_case, returncode, duration))
68 if retry:
69 self.progress.update_item(
70 '%s - %d' % (test_case, retry), index=1, size=int(not valid))
71 else:
72 self.progress.update_item(test_case, index=1, size=int(not valid))
73 if valid:
74 break
75 return out
76
77
78 def trace_test_cases(cmd, cwd_dir, test_cases, jobs, logname):
79 """Traces each test cases individually but all in parallel."""
80 assert os.path.isabs(cwd_dir) and os.path.isdir(cwd_dir), cwd_dir
81
82 if not test_cases:
83 return []
84
85 # Resolve any symlink.
86 cwd_dir = os.path.realpath(cwd_dir)
87 assert os.path.isdir(cwd_dir)
88
89 api = trace_inputs.get_api()
90 api.clean_trace(logname)
91
92 jobs = jobs or multiprocessing.cpu_count()
93 # Try to do black magic here by guessing a few of the run_test_cases.py
94 # flags. It's cheezy but it works.
95 for i, v in enumerate(cmd):
96 if v.endswith('run_test_cases.py'):
97 # Found it. Process the arguments here.
98 _, options, _ = run_test_cases.process_args(cmd[i:])
99 # Always override with the lowest value.
100 jobs = min(options.jobs, jobs)
101 break
102
103 columns = [('index', 0), ('size', len(test_cases))]
104 progress = threading_utils.Progress(columns)
105 with threading_utils.ThreadPoolWithProgress(
106 progress, jobs, jobs, len(test_cases)) as pool:
107 with api.get_tracer(logname) as tracer:
108 function = Tracer(tracer, cmd, cwd_dir, progress).map
109 for test_case in test_cases:
110 pool.add_task(0, function, test_case)
111
112 results = pool.join()
113 print('')
114 return results
115
116
117 def write_details(logname, outfile, root_dir, blacklist, results):
118 """Writes an .test_cases file with all the information about each test
119 case.
120 """
121 api = trace_inputs.get_api()
122 logs = dict(
123 (i.pop('trace'), i) for i in api.parse_log(logname, blacklist, None))
124 results_processed = {}
125 exception = None
126 for items in results:
127 item = items[-1]
128 assert item['valid']
129 # Load the results;
130 log_dict = logs[item['tracename']]
131 if log_dict.get('exception'):
132 exception = exception or log_dict['exception']
133 continue
134 trace_result = log_dict['results']
135 if root_dir:
136 trace_result = trace_result.strip_root(root_dir)
137 results_processed[item['test_case']] = {
138 'trace': trace_result.flatten(),
139 'duration': item['duration'],
140 'output': item['output'],
141 'returncode': item['returncode'],
142 }
143
144 # Make it dense if there is more than 20 results.
145 trace_inputs.write_json(
146 outfile,
147 results_processed,
148 len(results_processed) > 20)
149 if exception:
150 raise exception[0], exception[1], exception[2]
151
152
153 def main():
154 """CLI frontend to validate arguments."""
155 tools.disable_buffering()
156 parser = run_test_cases.OptionParserTestCases(
157 usage='%prog <options> [gtest]')
158 parser.format_description = lambda *_: parser.description
159 parser.add_option(
160 '-o', '--out',
161 help='output file, defaults to <executable>.test_cases')
162 parser.add_option(
163 '-r', '--root-dir',
164 help='Root directory under which file access should be noted')
165 parser.add_option(
166 '--trace-blacklist', action='append', default=[],
167 help='List of regexp to use as blacklist filter')
168 # TODO(maruel): Add support for options.timeout.
169 parser.remove_option('--timeout')
170 options, args = parser.parse_args()
171
172 if not args:
173 parser.error(
174 'Please provide the executable line to run, if you need fancy things '
175 'like xvfb, start this script from *inside* xvfb, it\'ll be much faster'
176 '.')
177
178 cmd = tools.fix_python_path(args)
179 cmd[0] = os.path.abspath(cmd[0])
180 if not os.path.isfile(cmd[0]):
181 parser.error('Tracing failed for: %s\nIt doesn\'t exit' % ' '.join(cmd))
182
183 if not options.out:
184 options.out = '%s.test_cases' % cmd[-1]
185 options.out = os.path.abspath(options.out)
186 if options.root_dir:
187 options.root_dir = os.path.abspath(options.root_dir)
188 logname = options.out + '.log'
189
190 test_cases = parser.process_gtest_options(cmd, os.getcwd(), options)
191
192 # Then run them.
193 print('Tracing...')
194 results = trace_test_cases(
195 cmd,
196 os.getcwd(),
197 test_cases,
198 options.jobs,
199 logname)
200 print('Reading trace logs...')
201 blacklist = trace_inputs.gen_blacklist(options.trace_blacklist)
202 write_details(logname, options.out, options.root_dir, blacklist, results)
203 return 0
204
205
206 if __name__ == '__main__':
207 sys.exit(main())
OLDNEW
« no previous file with comments | « swarm_client/googletest/tests/trace_test_cases_smoke_test.py ('k') | swarm_client/isolate.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698