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

Side by Side Diff: client/bin/factory.py

Issue 3340013: Fix status reporting and auto-seq logic. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/autotest.git
Patch Set: address comment, and patch factory_Verify Created 10 years, 3 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
« no previous file with comments | « no previous file | client/bin/factory_ui » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 # Copyright (c) 2010 The Chromium OS 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 5
6 # DESCRIPTION : 6 # DESCRIPTION :
7 # 7 #
8 # This library provides common types and routines for the factory ui 8 # This library provides common types and routines for the factory ui
9 # infrastructure. This library explicitly does not import gtk, to 9 # infrastructure. This library explicitly does not import gtk, to
10 # allow its use by the autotest control process. 10 # allow its use by the autotest control process.
(...skipping 20 matching lines...) Expand all
31 LOG_PATH = '/var/log/factory.log' 31 LOG_PATH = '/var/log/factory.log'
32 DATA_PREFIX = 'FACTORY_DATA:' 32 DATA_PREFIX = 'FACTORY_DATA:'
33 FINAL_VERIFICATION_TEST_UNIQUE_NAME = 'factory_Verify' 33 FINAL_VERIFICATION_TEST_UNIQUE_NAME = 'factory_Verify'
34 34
35 def log(s): 35 def log(s):
36 print >> sys.stderr, 'FACTORY: ' + s 36 print >> sys.stderr, 'FACTORY: ' + s
37 37
38 def log_shared_data(key, value): 38 def log_shared_data(key, value):
39 print >> sys.stderr, '%s %s=%s' % (DATA_PREFIX, key, repr(value)) 39 print >> sys.stderr, '%s %s=%s' % (DATA_PREFIX, key, repr(value))
40 40
41 def lookup_status_by_unique_name(unique_name, test_list, status_file_path):
42 """ quick way to determine the status of given test """
43 status_map = StatusMap(test_list, status_file_path)
44 testdb = status_map.test_db
45 xtest = testdb.get_test_by_unique_name(unique_name)
46 return status_map.lookup_status(xtest)
47 41
48 class FactoryTest: 42 class FactoryTest:
49 def __repr__(self): 43 def __repr__(self):
50 d = ['%s=%s' % (l, repr(v)) 44 d = ['%s=%s' % (l, repr(v))
51 for l, v in self.__dict__.items() 45 for l, v in self.__dict__.items()
52 if l != 'self'] 46 if l != 'self']
53 c = ('%s' % self.__class__).rpartition('.')[2] 47 c = ('%s' % self.__class__).rpartition('.')[2]
54 return '%s(%s)' % (c, ','.join(d)) 48 return '%s(%s)' % (c, ','.join(d))
55 49
56 class FactoryAutotestTest(FactoryTest): 50 class FactoryAutotestTest(FactoryTest):
(...skipping 13 matching lines...) Expand all
70 class AutomatedSequence(FactoryTest): 64 class AutomatedSequence(FactoryTest):
71 def __init__(self, label_en='', label_zw='', subtest_tag_prefix=None, 65 def __init__(self, label_en='', label_zw='', subtest_tag_prefix=None,
72 kbd_shortcut=None, subtest_list=[], unique_name=None): 66 kbd_shortcut=None, subtest_list=[], unique_name=None):
73 self.__dict__.update(vars()) 67 self.__dict__.update(vars())
74 68
75 class AutomatedSubTest(FactoryAutotestTest): 69 class AutomatedSubTest(FactoryAutotestTest):
76 def __init__(self, label_en='', label_zw='', autotest_name=None, 70 def __init__(self, label_en='', label_zw='', autotest_name=None,
77 dargs={}, drop_caches=False, unique_name=None): 71 dargs={}, drop_caches=False, unique_name=None):
78 self.__dict__.update(vars()) 72 self.__dict__.update(vars())
79 73
80 class AutomatedRebootSubTest(FactoryAutotestTest): 74 class AutomatedRebootSubTest(AutomatedSubTest):
81 def __init__(self, label_en='', label_zw='', iterations=None, 75 def __init__(self, label_en='', label_zw='', iterations=None,
82 autotest_name='factory_RebootStub', dargs={}, 76 autotest_name='factory_RebootStub', dargs={},
83 drop_caches=False, unique_name=None): 77 drop_caches=False, unique_name=None):
84 self.__dict__.update(vars()) 78 self.__dict__.update(vars())
85 79
86 80
81 class KbdShortcutDatabase:
82 '''Track the bindings between keyboard shortcuts and tests.'''
83
84 def __init__(self, test_list, test_db):
85 self._kbd_shortcut_map = dict(
86 (test.kbd_shortcut, test) for test in test_list)
87
88 # Validate keyboard shortcut uniqueness.
89 assert(None not in self._kbd_shortcut_map)
90 delta = set(test_list) - set(self._kbd_shortcut_map.values())
91 for test in delta:
92 collision = kbd_shortcut_map[test.kbd_shortcut]
93 log('ERROR: tests %s and %s both have kbd_shortcut %s' %
94 (test_db.get_unique_id_str(test),
95 test_db.get_unique_id_str(collision),
96 test.kbd_shortcut))
97 assert not delta
98
99 def get_shortcut_keys(self):
100 return set(self._kbd_shortcut_map)
101
102 def lookup_test(self, kbd_shortcut):
103 return self._kbd_shortcut_map.get(kbd_shortcut)
104
105
87 class TestDatabase: 106 class TestDatabase:
107 '''This class parses a test_list and allows searching for tests or
108 their attributes. It also generates tag_prefix values for each
109 runnable test. Autotest allows tests with the same name to be
110 uniquely identified by the "tag" parameter to the job.run_test()
111 function. The factory system generates this value as the
112 combination of a tag_prefix value and a counter that tracks how
113 many times a test has run. Tests are identified uniquely in the
114 status log by both the tag_prefix and their autotest name. These
115 values are referred to here as the unique_details for the test.'''
88 116
89 def __init__(self, test_list): 117 def __init__(self, test_list):
90 self.test_queue = [t for t in reversed(test_list)] 118 self._test_list = test_list
119 self._subtest_set = set()
91 self._subtest_parent_map = {} 120 self._subtest_parent_map = {}
92 self._tag_prefix_map = {} 121 self._tag_prefix_map = {}
93 for test in test_list: 122 for test in test_list:
94 if not isinstance(test, AutomatedSequence): 123 if not isinstance(test, AutomatedSequence):
95 self._tag_prefix_map[test] = test.kbd_shortcut 124 self._tag_prefix_map[test] = test.kbd_shortcut
96 continue 125 continue
97 step_count = 1 126 step_count = 1
98 for subtest in test.subtest_list: 127 for subtest in test.subtest_list:
99 self._subtest_parent_map[subtest] = test 128 self._subtest_parent_map[subtest] = test
129 self._subtest_set.add(subtest)
100 if not isinstance(subtest, FactoryAutotestTest): 130 if not isinstance(subtest, FactoryAutotestTest):
101 continue 131 continue
102 tag_prefix = ('%s_s%d' % (test.subtest_tag_prefix, step_count)) 132 tag_prefix = ('%s_s%d' % (test.subtest_tag_prefix, step_count))
103 self._tag_prefix_map[subtest] = tag_prefix 133 self._tag_prefix_map[subtest] = tag_prefix
104 step_count += 1 134 step_count += 1
105 self.seq_test_set = set(test for test in test_list 135 self._tag_prefix_to_subtest_map = dict(
106 if isinstance(test, AutomatedSequence)) 136 (self._tag_prefix_map[st], st) for st in self._subtest_set)
107 self.subtest_set = set(reduce(lambda x, y: x + y, 137 self._unique_details_map = dict(
108 [test.subtest_list for test in 138 (self.get_unique_details(t), t) for t in self.get_all_tests()
109 self.seq_test_set], [])) 139 if isinstance(t, FactoryAutotestTest))
110 self._subtest_map = dict((self._tag_prefix_map[st], st) 140 self._unique_name_map = dict(
111 for st in self.subtest_set) 141 (t.unique_name, t) for t in self.get_all_tests()
112 self.all_tests = set(test_list) | self.subtest_set 142 if getattr(t, 'unique_name', None) is not None)
113 self._unique_name_map = dict((t.unique_name, t) for t in self.all_tests
114 if isinstance(t, FactoryAutotestTest)
115 and t.unique_name is not None)
116 self._unique_details_map = dict((self.get_unique_details(t), t)
117 for t in self.all_tests)
118 self._kbd_shortcut_map = dict((test.kbd_shortcut, test)
119 for test in test_list)
120 self.kbd_shortcut_set = set(self._kbd_shortcut_map)
121 143
122 # Validate keyboard shortcut uniqueness. 144 def get_test_by_unique_details(self, autotest_name, tag_prefix):
123 assert(None not in self.kbd_shortcut_set) 145 return self._unique_details_map.get((autotest_name, tag_prefix))
124 delta = set(test_list) - set(self._kbd_shortcut_map.values())
125 for test in delta:
126 collision = kbd_shortcut_map[test.kbd_shortcut]
127 log('ERROR: tests %s and %s both have kbd_shortcut %s' %
128 (test.label_en, collision.label_en, test.kbd_shortcut))
129 assert not delta
130 146
131 def get_tag_prefix(self, test): 147 def get_tag_prefix(self, test):
132 return self._tag_prefix_map[test] 148 return self._tag_prefix_map[test]
133 149
134 def get_unique_details(self, test): 150 def get_unique_details(self, test):
135 if isinstance(test, AutomatedSequence): 151 return (test.autotest_name, self.get_tag_prefix(test))
136 return test.subtest_tag_prefix
137 return '%s.%s' % (test.autotest_name, self.get_tag_prefix(test))
138
139 def get_test_by_unique_details(self, autotest_name, tag_prefix):
140 unique_details = '%s.%s' % (autotest_name, tag_prefix)
141 return self._unique_details_map.get(unique_details)
142
143 def get_test_by_kbd_shortcut(self, kbd_shortcut):
144 return self._kbd_shortcut_map.get(kbd_shortcut)
145 152
146 def get_test_by_unique_name(self, unique_name): 153 def get_test_by_unique_name(self, unique_name):
147 return self._unique_name_map.get(unique_name) 154 return self._unique_name_map.get(unique_name)
148 155
149 def get_subtest_parent(self, test): 156 def get_subtest_parent(self, test):
150 return self._subtest_parent_map.get(test) 157 return self._subtest_parent_map.get(test)
151 158
152 def get_subtest_by_tag_prefix(self, tag_prefix): 159 def get_subtest_by_tag_prefix(self, tag_prefix):
153 return self._subtest_map.get(tag_prefix) 160 return self._tag_prefix_to_subtest_map.get(tag_prefix)
161
162 def get_automated_sequences(self):
163 return [test for test in self._test_list
164 if isinstance(test, AutomatedSequence)]
165
166 def get_all_tests(self):
167 return set(self._test_list) | self._subtest_set
168
169 def get_unique_id_str(self, test):
170 '''Intended primarily to identify tests for debugging.'''
171 if test is None:
172 return None
173 if isinstance(test, AutomatedSequence):
174 return test.subtest_tag_prefix
175 return '%s.%s' % self.get_unique_details(test)
154 176
155 177
156 class StatusMap: 178 class StatusMap:
179 '''Parse the contents of an autotest status file for factory tests
180 into a database containing status, count, and error message
181 information. On __init__ the status file is parsed once. Changes
182 to the file are dealt with by running read_new_data(). Complexity
183 is introduced here because AutomatedSequences are not directly
184 represented in the status file and their status must be derived
185 from subtest results.'''
157 186
158 class Entry: 187 class Entry:
159 188
160 def __init__(self): 189 def __init__(self):
161 self.status = UNTESTED 190 self.status = UNTESTED
162 self.count = 0 191 self.count = 0
163 self.label_box = None
164 self.error_msg = None 192 self.error_msg = None
165 193
166 def __init__(self, test_list, status_file_path): 194 def __init__(self, test_list, status_file_path, test_db=None,
167 self.test_db = TestDatabase(test_list) 195 status_change_callback=None):
168 all_tests = self.test_db.all_tests 196 self._test_list = [test for test in test_list]
169 self._status_map = dict((t, StatusMap.Entry()) for t in all_tests) 197 self._test_db = test_db if test_db else TestDatabase(test_list)
198 self._status_map = dict(
199 (test, StatusMap.Entry()) for test in self._test_db.get_all_tests())
170 self._status_file_path = status_file_path 200 self._status_file_path = status_file_path
171 self._status_file_pos = 0 201 self._status_file_pos = 0
202 self._active_automated_seq = None
203 self._status_change_callback = status_change_callback
172 self.read_new_data() 204 self.read_new_data()
173 205
174 def lookup_status(self, test): 206 def lookup_status(self, test, min_count=0):
175 return self._status_map[test].status 207 entry = self._status_map[test]
208 return entry.status if entry.count >= min_count else UNTESTED
176 209
177 def lookup_count(self, test): 210 def lookup_count(self, test):
178 return self._status_map[test].count 211 if isinstance(test, AutomatedSubTest):
179 212 parent = self._test_db.get_subtest_parent(test)
180 def lookup_label_box(self, test): 213 return self._status_map[parent].count
181 return self._status_map[test].label_box 214 else:
215 return self._status_map[test].count
182 216
183 def lookup_error_msg(self, test): 217 def lookup_error_msg(self, test):
184 return self._status_map[test].error_msg 218 return self._status_map[test].error_msg
185 219
186 def lookup_tag(self, test): 220 def filter_by_status(self, target_status):
187 tag_prefix = self.test_db.get_tag_prefix(test)
188 count = self._status_map[test].count
189 return '%s_%s' % (tag_prefix, count)
190
191 def incr_count(self, test):
192 self._status_map[test].count += 1
193
194 def filter(self, target_status):
195 comp = (isinstance(target_status, list) and 221 comp = (isinstance(target_status, list) and
196 (lambda s: s in target_status) or 222 (lambda s: s in target_status) or
197 (lambda s: s == target_status)) 223 (lambda s: s == target_status))
198 return [t for t in self.test_db.test_queue 224 return [test for test in self._test_db.all_tests
199 if comp(self.lookup_status(t))] 225 if comp(self.lookup_status(test))]
200 226
201 def next_untested(self): 227 def next_untested(self):
202 remaining = self.filter(UNTESTED) 228 for test in self._test_list:
203 unique_details = [self.test_db.get_unique_details(t) for t in remaining] 229 if self.lookup_status(test) == UNTESTED:
204 log('remaining untested = [%s]' % ', '.join(unique_details)) 230 return test
205 return remaining is not [] and remaining.pop() or None 231 return None
232
233 def get_active_top_level_test(self):
234 if self._active_automated_seq:
235 return self._active_automated_seq
236 active_tests = [test for test in self._test_list
237 if self.lookup_status(test) == ACTIVE]
238 if len(active_tests) > 1:
239 log('ERROR -- multiple active top level tests %s' %
240 repr([self._test_db.get_unique_id_str(test)
241 for test in active_tests]))
242 return active_tests.pop() if active_tests != [] else None
206 243
207 def read_new_data(self): 244 def read_new_data(self):
208 with open(self._status_file_path) as file: 245 with open(self._status_file_path) as file:
209 file.seek(self._status_file_pos) 246 file.seek(self._status_file_pos)
210 for line in file: 247 for line in file:
211 cols = line.strip().split('\t') + [''] 248 cols = line.strip().split('\t') + ['']
212 code = cols[0] 249 code = cols[0]
213 test_id = cols[1] 250 test_id = cols[1]
214 if code not in STATUS_CODE_MAP or test_id == '----': 251 if code not in STATUS_CODE_MAP or test_id == '----':
215 continue 252 continue
216 status = STATUS_CODE_MAP[code] 253 status = STATUS_CODE_MAP[code]
217 error_msg = status == FAILED and cols[len(cols) - 2] or None 254 error_msg = status == FAILED and cols[len(cols) - 2] or None
218 log('reading code = %s, test_id = %s, error_msg = "%s"'
219 % (code, test_id, error_msg))
220 autotest_name, _, tag = test_id.rpartition('.') 255 autotest_name, _, tag = test_id.rpartition('.')
221 tag_prefix, _, count = tag.rpartition('_') 256 tag_prefix, _, count = tag.rpartition('_')
222 test = self.test_db.get_test_by_unique_details( 257 test = self._test_db.get_test_by_unique_details(
223 autotest_name, tag_prefix) 258 autotest_name, tag_prefix)
224 if test is None: 259 if test is None:
225 log('ignoring update (%s) for test "%s" "%s"' % 260 log('status map ignoring update (%s) for test %s %s' %
226 (status, autotest_name, tag_prefix)) 261 (status, repr(autotest_name), repr(tag_prefix)))
227 continue 262 continue
228 self.update(test, status, int(count), error_msg) 263 self.update(test, status, int(count), error_msg)
229 map(self.update_seq_test, self.test_db.seq_test_set)
230 self._status_file_pos = file.tell() 264 self._status_file_pos = file.tell()
231 265
232 def get_active_top_level_test(self):
233 active_tests = set(self.filter(ACTIVE)) - self.test_db.subtest_set
234 return active_tests and active_tests.pop() or None
235
236 def get_active_subtest(self):
237 active_subtests = set(self.filter(ACTIVE)) & self.test_db.subtest_set
238 return active_subtests and active_subtests.pop() or None
239
240 def register_active(self, test):
241 active_tests = set(self.filter(ACTIVE))
242 assert(test not in active_tests)
243 if test in self.test_db.subtest_set:
244 parent_seq_test = self.test_db.get_subtest_parent(test)
245 active_tests -= set([parent_seq_test])
246 for bad_test in active_tests:
247 unique_details = self.test_db.get_unique_details(bad_test)
248 log('WARNING: assuming test %s FAILED (status log has no data)' %
249 unique_details)
250 self.update(bad_test, FAILED, self.lookup_count(bad_test),
251 'assumed FAILED (status log has no data)')
252
253 def update(self, test, status, count, error_msg): 266 def update(self, test, status, count, error_msg):
254 entry = self._status_map[test] 267 entry = self._status_map[test]
255 unique_details = self.test_db.get_unique_details(test) 268 unique_id_str = self._test_db.get_unique_id_str(test)
256 if count < entry.count: 269 if count < entry.count:
257 log('ERROR: count regression for %s (%d -> %d)' % 270 log('ignoring older data for %s (data count %d < state count %d)' %
258 (unique_details, entry.count, count)) 271 (unique_id_str, count, entry.count))
272 return
259 if isinstance(test, InformationScreen) and status in [PASSED, FAILED]: 273 if isinstance(test, InformationScreen) and status in [PASSED, FAILED]:
260 status = UNTESTED 274 status = UNTESTED
275 parent_as = self._test_db.get_subtest_parent(test)
261 if status != entry.status: 276 if status != entry.status:
262 log('status change for %s : %s/%s -> %s/%s' % 277 log('status change for %s : %s/%s -> %s/%s (as = %s)' %
263 (unique_details, entry.status, entry.count, status, count)) 278 (unique_id_str, entry.status, entry.count, status,
264 if entry.label_box is not None: 279 count, self._test_db.get_unique_id_str(parent_as)))
265 entry.label_box.update(status) 280 if self._status_change_callback is not None:
266 if status == ACTIVE: 281 self._status_change_callback(test, status)
267 self.register_active(test)
268 entry.status = status 282 entry.status = status
269 entry.count = count 283 entry.count = count
270 entry.error_msg = error_msg 284 entry.error_msg = error_msg
271 log('%s new status = %s' % 285 if (status == ACTIVE and not isinstance(test, AutomatedSequence) and
272 (unique_details, self._status_map[test].status)) 286 self._active_automated_seq != parent_as):
287 if self._active_automated_seq is not None:
288 self.update_automated_sequence(self._active_automated_seq)
289 self._active_automated_seq = parent_as
290 if parent_as is not None:
291 self.update_automated_sequence(parent_as)
273 292
274 def update_seq_test(self, test): 293 def update_automated_sequence(self, test):
275 subtest_status_set = set(map(self.lookup_status, test.subtest_list)) 294 max_count = max([self._status_map[st].count
276 max_count = max(map(self.lookup_count, test.subtest_list)) 295 for st in test.subtest_list])
296 lookup_fn = lambda x: self.lookup_status(x, min_count=max_count)
297 subtest_status_set = set(
298 self.lookup_status(subtest) for subtest in test.subtest_list)
299 log('automated sequence %s status set = %s' % (
300 self._test_db.get_unique_id_str(test),
301 repr(subtest_status_set)))
277 if len(subtest_status_set) == 1: 302 if len(subtest_status_set) == 1:
278 status = subtest_status_set.pop() 303 status = subtest_status_set.pop()
279 elif subtest_status_set == set([PASSED, FAILED]): 304 elif (test == self._active_automated_seq and
305 FAILED not in subtest_status_set):
306 status = ACTIVE
307 else:
280 status = FAILED 308 status = FAILED
281 else:
282 status = ACTIVE
283 self.update(test, status, max_count, None) 309 self.update(test, status, max_count, None)
284 310
285 def set_label_box(self, test, label_box):
286 entry = self._status_map[test]
287 entry.label_box = label_box
288 label_box.update(entry.status)
289
290 311
291 class LogData: 312 class LogData:
313 '''Parse the factory log looking for specially formatted
314 name-value declarations and recording the last of any such
315 bindings in a dict. Data in the right format is written to the
316 log using log_shared_data().'''
292 317
293 def __init__(self): 318 def __init__(self):
294 self._log_file_pos = 0 319 self._log_file_pos = 0
295 self.shared_dict = {} 320 self.shared_dict = {}
296 self.read_new_data() 321 self.read_new_data()
297 322
298 def read_new_data(self): 323 def read_new_data(self):
299 with open(LOG_PATH) as file: 324 with open(LOG_PATH) as file:
300 file.seek(self._log_file_pos) 325 file.seek(self._log_file_pos)
301 for line in file: 326 for line in file:
302 parts = line.rsplit(DATA_PREFIX, 1) 327 parts = line.rsplit(DATA_PREFIX, 1)
303 if not len(parts) == 2: 328 if not len(parts) == 2:
304 continue 329 continue
305 key, raw_value = parts.pop().strip().split('=', 1) 330 key, raw_value = parts.pop().strip().split('=', 1)
306 log('updating shared_dict[%s]=%s' % (key, raw_value)) 331 log('updating shared_dict[%s]=%s' % (key, raw_value))
307 self.shared_dict[key] = eval(raw_value) 332 self.shared_dict[key] = eval(raw_value)
308 self._log_file_pos = file.tell() 333 self._log_file_pos = file.tell()
309 334
310 def get(self, key): 335 def get(self, key):
311 return self.shared_dict.get(key) 336 return self.shared_dict.get(key)
312 337
313 338
314 class ControlState: 339 class ControlState:
340 '''Track the state needed to run and terminate factory tests. The
341 shared data written to the factory log records the pid information
342 for each test as it gets run. If the factory UI sees a keyboard
343 shortcut event, it sends a SIGUSR1 event to the control process,
344 which then uses the log information to terminate the running
345 test.'''
315 346
316 def __init__(self, job, test_list, status_map, status_file_path, nuke_fn): 347 def __init__(self, job, test_list, test_db, status_map,
348 status_file_path, nuke_fn):
317 self._job = job 349 self._job = job
318 self._status_map = status_map 350 self._status_map = status_map
351 self._kbd_shortcut_db = KbdShortcutDatabase(test_list, test_db)
352 self._test_db = test_db
319 self._log_data = LogData() 353 self._log_data = LogData()
320 self._std_dargs = { 354 self._std_dargs = {
321 'status_file_path' : status_file_path, 355 'status_file_path' : status_file_path,
322 'test_list': test_list} 356 'test_list': test_list}
323 self._nuke_fn = nuke_fn 357 self._nuke_fn = nuke_fn
324 self.activated_kbd_shortcut_test = None
325 signal.signal(signal.SIGUSR1, self.kill_current_test_callback) 358 signal.signal(signal.SIGUSR1, self.kill_current_test_callback)
326 359
327 def kill_current_test_callback(self, signum, frame): 360 def kill_current_test_callback(self, signum, frame):
328 self._log_data.read_new_data() 361 self._log_data.read_new_data()
329 active_test_data = self._log_data.get('active_test_data') 362 active_test_data = self._log_data.get('active_test_data')
330 log('KILLING active_test_data %s' % repr(active_test_data))
331 if active_test_data is not None: 363 if active_test_data is not None:
364 log('SIGUSR1 ... KILLING active test %s' % repr(active_test_data))
332 self._nuke_fn(*active_test_data) 365 self._nuke_fn(*active_test_data)
366 else:
367 log('SIGUSR1 ... KILLING NOTHING, no active test')
333 368
334 def run_test(self, test): 369 def process_kbd_shortcut_activation(self):
370 kbd_shortcut = self._log_data.get('activated_kbd_shortcut')
371 if kbd_shortcut is None:
372 return None
373 target_test = self._kbd_shortcut_db.lookup_test(kbd_shortcut)
374 log('activated kbd_shortcut %s -> %s' % (
375 kbd_shortcut, self._test_db.get_unique_id_str(target_test)))
335 log_shared_data('activated_kbd_shortcut', None) 376 log_shared_data('activated_kbd_shortcut', None)
377 return target_test
336 378
337 self._status_map.incr_count(test) 379 def run_test(self, test, count):
338 self._log_data.read_new_data() 380 self._log_data.read_new_data()
339 test_tag = self._status_map.lookup_tag(test) 381 test_tag = '%s_%s' % (self._test_db.get_tag_prefix(test), count)
340 dargs = {} 382 dargs = {}
341 dargs.update(test.dargs) 383 dargs.update(test.dargs)
342 dargs.update(self._std_dargs) 384 dargs.update(self._std_dargs)
343 dargs.update({'tag': test_tag, 385 dargs.update({'tag': test_tag,
344 'subtest_tag': test_tag, 386 'subtest_tag': test_tag,
345 'shared_dict': self._log_data.shared_dict}) 387 'shared_dict': self._log_data.shared_dict})
346
347 self._job.factory_shared_dict = self._log_data.shared_dict 388 self._job.factory_shared_dict = self._log_data.shared_dict
348 389 self._job.drop_caches_between_iterations = test.drop_caches
349 log('control shared dict = %s' % repr(self._log_data.shared_dict))
350
351 if test.drop_caches:
352 self._job.drop_caches_between_iterations = True
353 self.activated_kbd_shortcut_test = None
354
355 self._job.run_test(test.autotest_name, **dargs) 390 self._job.run_test(test.autotest_name, **dargs)
356
357 self._job.drop_caches_between_iterations = False 391 self._job.drop_caches_between_iterations = False
358 self._log_data.read_new_data() 392 self._log_data.read_new_data()
359 kbd_shortcut = self._log_data.shared_dict.pop( 393 return self.process_kbd_shortcut_activation()
360 'activated_kbd_shortcut', None) 394
361 if kbd_shortcut is not None: 395
362 test_db = self._status_map.test_db 396 def lookup_status_by_unique_name(unique_name, test_list, status_file_path):
363 target_test = test_db.get_test_by_kbd_shortcut(kbd_shortcut) 397 """Determine the status of given test. Somewhat heavyweight,
364 self.activated_kbd_shortcut_test = target_test 398 since it parses the status file."""
365 log('kbd_shortcut %s -> %s)' % ( 399 test = TestDatabase(test_list).get_test_by_unique_name(unique_name)
366 kbd_shortcut, test_db.get_unique_details(target_test))) 400 return StatusMap(test_list, status_file_path, test_db).lookup_status(test)
OLDNEW
« no previous file with comments | « no previous file | client/bin/factory_ui » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698