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

Side by Side Diff: scripts/slave/unittests/expect_tests/pipeline.py

Issue 355143002: Set coverage path globs on a per-Test basis instead of in main(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 6 years, 5 months 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
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import Queue 5 import Queue
6 import glob 6 import glob
7 import inspect
7 import logging 8 import logging
8 import multiprocessing 9 import multiprocessing
9 import re 10 import re
10 import signal 11 import signal
11 import traceback 12 import traceback
12 13
13 from cStringIO import StringIO 14 from cStringIO import StringIO
14 15
15 from .type_definitions import ( 16 from .type_definitions import (
16 Test, UnknownError, TestError, NoMatchingTestsError, MultiTest, 17 Test, UnknownError, TestError, NoMatchingTestsError, MultiTest,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 matcher = re.compile('^.*$') 54 matcher = re.compile('^.*$')
54 55
55 neg_matcher = re.compile( 56 neg_matcher = re.compile(
56 '^%s$' % '|'.join('(?:%s)' % glob.fnmatch.translate(g[1:]) 57 '^%s$' % '|'.join('(?:%s)' % glob.fnmatch.translate(g[1:])
57 for g in globs if g[0] == '-')) 58 for g in globs if g[0] == '-'))
58 59
59 def generate_tests(): 60 def generate_tests():
60 paths_seen = set() 61 paths_seen = set()
61 seen_tests = False 62 seen_tests = False
62 try: 63 try:
63 for root_test in gen(): 64 with cover_ctx:
65 gen_inst = gen()
66
67 while not kill_switch.is_set():
68 with cover_ctx:
69 root_test = next(gen_inst)
70
64 if kill_switch.is_set(): 71 if kill_switch.is_set():
Vadim Sh. 2014/06/27 18:06:48 Is it still needed here?
iannucci 2014/06/28 08:58:17 I guess not, but it doesn't hurt, especially if ne
65 break 72 break
66 73
67 ok_tests = [] 74 ok_tests = []
68 75
69 if isinstance(root_test, MultiTest): 76 if isinstance(root_test, MultiTest):
70 subtests = root_test.tests 77 subtests = root_test.tests
71 else: 78 else:
72 subtests = [root_test] 79 subtests = [root_test]
73 80
74 for subtest in subtests: 81 for subtest in subtests:
(...skipping 13 matching lines...) Expand all
88 name = subtest.name 95 name = subtest.name
89 if not neg_matcher.match(name) and matcher.match(name): 96 if not neg_matcher.match(name) and matcher.match(name):
90 ok_tests.append(subtest) 97 ok_tests.append(subtest)
91 98
92 if ok_tests: 99 if ok_tests:
93 seen_tests = True 100 seen_tests = True
94 yield root_test.restrict(ok_tests) 101 yield root_test.restrict(ok_tests)
95 102
96 if not seen_tests: 103 if not seen_tests:
97 result_queue.put_nowait(NoMatchingTestsError()) 104 result_queue.put_nowait(NoMatchingTestsError())
105 except StopIteration:
106 pass
98 except KeyboardInterrupt: 107 except KeyboardInterrupt:
99 pass 108 pass
100 finally: 109 finally:
101 for _ in xrange(opts.jobs): 110 for _ in xrange(opts.jobs):
102 test_queue.put_nowait(None) 111 test_queue.put_nowait(None)
103 112
104 113
105 next_stage = (result_queue if opts.handler.SKIP_RUNLOOP else test_queue) 114 next_stage = (result_queue if opts.handler.SKIP_RUNLOOP else test_queue)
106 with cover_ctx: 115 opts.handler.gen_stage_loop(opts, generate_tests(), next_stage.put_nowait,
107 opts.handler.gen_stage_loop(opts, generate_tests(), next_stage.put_nowait, 116 result_queue.put_nowait)
108 result_queue.put_nowait)
109 117
110 118
111 def run_loop_process(test_queue, result_queue, opts, kill_switch, cover_ctx): 119 def run_loop_process(test_queue, result_queue, opts, kill_switch, cover_ctx):
112 """Consume `Test` instances from |test_queue|, run them, and yield the results 120 """Consume `Test` instances from |test_queue|, run them, and yield the results
113 into opts.run_stage_loop(). 121 into opts.run_stage_loop().
114 122
115 Generates coverage data as a side-effect. 123 Generates coverage data as a side-effect.
124
116 @type test_queue: multiprocessing.Queue() 125 @type test_queue: multiprocessing.Queue()
117 @type result_queue: multiprocessing.Queue() 126 @type result_queue: multiprocessing.Queue()
118 @type opts: argparse.Namespace 127 @type opts: argparse.Namespace
119 @type kill_switch: multiprocessing.Event() 128 @type kill_switch: multiprocessing.Event()
120 @type cover_ctx: cover.CoverageContext().create_subprocess_context() 129 @type cover_ctx: cover.CoverageContext().create_subprocess_context()
121 """ 130 """
122 logstream = ResetableStringIO() 131 logstream = ResetableStringIO()
123 logger = logging.getLogger() 132 logger = logging.getLogger()
124 logger.setLevel(logging.DEBUG) 133 logger.setLevel(logging.DEBUG)
125 shandler = logging.StreamHandler(logstream) 134 shandler = logging.StreamHandler(logstream)
126 shandler.setFormatter( 135 shandler.setFormatter(
127 logging.Formatter('%(levelname)s: %(message)s')) 136 logging.Formatter('%(levelname)s: %(message)s'))
128 logger.addHandler(shandler) 137 logger.addHandler(shandler)
129 138
130 SKIP = object() 139 SKIP = object()
131 def process_test(subtest): 140 def process_test(subtest):
132 logstream.reset() 141 logstream.reset()
133 subresult = subtest.run() 142 with cover_ctx(include=subtest.coverage_includes()):
143 subresult = subtest.run()
134 if isinstance(subresult, TestError): 144 if isinstance(subresult, TestError):
135 result_queue.put_nowait(subresult) 145 result_queue.put_nowait(subresult)
136 return SKIP 146 return SKIP
137 elif not isinstance(subresult, Result): 147 elif not isinstance(subresult, Result):
138 result_queue.put_nowait( 148 result_queue.put_nowait(
139 TestError( 149 TestError(
140 subtest, 150 subtest,
141 'Got non-Result instance from test: %r' % subresult)) 151 'Got non-Result instance from test: %r' % subresult))
142 return SKIP 152 return SKIP
143 return subresult 153 return subresult
(...skipping 12 matching lines...) Expand all
156 for subtest, subresult in test.process(process_test): 166 for subtest, subresult in test.process(process_test):
157 if subresult is not SKIP: 167 if subresult is not SKIP:
158 yield subtest, subresult, logstream.getvalue().splitlines() 168 yield subtest, subresult, logstream.getvalue().splitlines()
159 except Exception: 169 except Exception:
160 result_queue.put_nowait( 170 result_queue.put_nowait(
161 TestError(test, traceback.format_exc(), 171 TestError(test, traceback.format_exc(),
162 logstream.getvalue().splitlines())) 172 logstream.getvalue().splitlines()))
163 except KeyboardInterrupt: 173 except KeyboardInterrupt:
164 pass 174 pass
165 175
166 with cover_ctx: 176 opts.handler.run_stage_loop(opts, generate_tests_results(),
167 opts.handler.run_stage_loop(opts, generate_tests_results(), 177 result_queue.put_nowait)
168 result_queue.put_nowait)
169 178
170 179
171 def result_loop(test_gen, cover_ctx, opts): 180 def result_loop(test_gen, cover_ctx, opts):
172 kill_switch = multiprocessing.Event() 181 kill_switch = multiprocessing.Event()
173 def handle_killswitch(*_): 182 def handle_killswitch(*_):
174 kill_switch.set() 183 kill_switch.set()
175 # Reset the signal to DFL so that double ctrl-C kills us for sure. 184 # Reset the signal to DFL so that double ctrl-C kills us for sure.
176 signal.signal(signal.SIGINT, signal.SIG_DFL) 185 signal.signal(signal.SIGINT, signal.SIG_DFL)
177 signal.signal(signal.SIGTERM, signal.SIG_DFL) 186 signal.signal(signal.SIGTERM, signal.SIG_DFL)
178 signal.signal(signal.SIGINT, handle_killswitch) 187 signal.signal(signal.SIGINT, handle_killswitch)
179 signal.signal(signal.SIGTERM, handle_killswitch) 188 signal.signal(signal.SIGTERM, handle_killswitch)
180 189
181 test_queue = multiprocessing.Queue() 190 test_queue = multiprocessing.Queue()
182 result_queue = multiprocessing.Queue() 191 result_queue = multiprocessing.Queue()
183 192
193 gen_cover_ctx = cover_ctx
194 if cover_ctx.enabled:
195 if hasattr(test_gen, '_covers'):
196 # decorated with expect_tests.covers
197 gen_cover = test_gen._covers() # pylint: disable=W0212
Vadim Sh. 2014/06/27 18:06:48 I forgot what type test_gen has here. Why do you
iannucci 2014/06/28 08:58:17 it's a user function. Moved this all to util and u
198 else:
199 gen_cover = [inspect.getabsfile(test_gen)]
Vadim Sh. 2014/06/27 18:06:48 Cover single file? Also, have you verified it work
iannucci 2014/06/28 08:58:17 It seems to always give back a .py file. I have py
200 gen_cover_ctx = cover_ctx(include=gen_cover)
201
184 test_gen_args = ( 202 test_gen_args = (
185 test_gen, test_queue, result_queue, opts, kill_switch, cover_ctx) 203 test_gen, test_queue, result_queue, opts, kill_switch, gen_cover_ctx)
186 204
187 procs = [] 205 procs = []
188 if opts.handler.SKIP_RUNLOOP: 206 if opts.handler.SKIP_RUNLOOP:
189 gen_loop_process(*test_gen_args) 207 gen_loop_process(*test_gen_args)
190 else: 208 else:
191 procs = [multiprocessing.Process( 209 procs = [multiprocessing.Process(
192 target=gen_loop_process, args=test_gen_args)] 210 target=gen_loop_process, args=test_gen_args)]
193 211
194 procs += [ 212 procs += [
195 multiprocessing.Process( 213 multiprocessing.Process(
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 except ResultStageAbort: 247 except ResultStageAbort:
230 pass 248 pass
231 249
232 for p in procs: 250 for p in procs:
233 p.join() 251 p.join()
234 252
235 if not kill_switch.is_set() and not result_queue.empty(): 253 if not kill_switch.is_set() and not result_queue.empty():
236 error = True 254 error = True
237 255
238 return error, kill_switch.is_set() 256 return error, kill_switch.is_set()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698