Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 | 7 |
| 8 # DESCRIPTION : | 8 # DESCRIPTION : |
| 9 # | 9 # |
| 10 # This UI is intended to be used by the factory autotest suite to | 10 # This UI is intended to be used by the factory autotest suite to |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 import select | 31 import select |
| 32 import signal | 32 import signal |
| 33 import subprocess | 33 import subprocess |
| 34 import sys | 34 import sys |
| 35 import time | 35 import time |
| 36 | 36 |
| 37 import common | 37 import common |
| 38 import factory | 38 import factory |
| 39 import factory_state | 39 import factory_state |
| 40 import factory_ui_lib as ful | 40 import factory_ui_lib as ful |
| 41 import utils | |
| 41 | 42 |
| 42 from gtk import gdk | 43 from gtk import gdk |
| 43 from Xlib import X | 44 from Xlib import X |
| 44 from Xlib.display import Display as X_Display | 45 from Xlib.display import Display as X_Display |
| 45 | 46 |
| 46 | 47 |
| 47 # These definitions are expose these classes directly into this | 48 # These definitions are expose these classes directly into this |
| 48 # namespace, so that the test_list that is sent from the control file | 49 # namespace, so that the test_list that is sent from the control file |
| 49 # can have cleaner syntax. These are done in this fashion, as opposed | 50 # can have cleaner syntax. These are done in this fashion, as opposed |
| 50 # to "from factory import <class>" to work-around Python namespace | 51 # to "from factory import <class>" to work-around Python namespace |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 251 for name, status in test_state.get_all_tests().items(): | 252 for name, status in test_state.get_all_tests().items(): |
| 252 test = test_db.get_test_by_unique_id_str(name) | 253 test = test_db.get_test_by_unique_id_str(name) |
| 253 ui_state.status_change_callback(test, status) | 254 ui_state.status_change_callback(test, status) |
| 254 if (status == factory.ACTIVE and | 255 if (status == factory.ACTIVE and |
| 255 (not isinstance(test, AutomatedSubTest))): | 256 (not isinstance(test, AutomatedSubTest))): |
| 256 ui_state.set_active_test(test_db, test) | 257 ui_state.set_active_test(test_db, test) |
| 257 except Exception, e: | 258 except Exception, e: |
| 258 factory.log('state_change_handler got exception: %s', repr(e)) | 259 factory.log('state_change_handler got exception: %s', repr(e)) |
| 259 return True | 260 return True |
| 260 | 261 |
| 262 def kill_active_test(control_pid): | |
| 263 # Currently we kill the active test directly. | |
| 264 # If we want to use the old way - notify main control to kill it, | |
| 265 # then send USR1 to main control instead: | |
| 266 # os.kill(control_pid, signal.SIGUSR1) | |
| 267 active_test_data = factory.get_shared_data('active_test_data') | |
| 268 if active_test_data is None: | |
|
josephsih1
2011/03/04 02:13:11
As in kill_current_test_callback() in factory.py,
Hung-Te
2011/03/04 02:21:28
Actually we should (almost) never see this, becaus
| |
| 269 return | |
| 270 factory.log('KILLING active test %s' % repr(active_test_data)) | |
| 271 try: | |
| 272 utils.nuke_pid(active_test_data[1]) | |
|
josephsih1
2011/03/04 02:13:11
In the original design, the subprocess killing is
Hung-Te
2011/03/04 02:21:28
These are in different processes, so it would not
| |
| 273 # To remove the dependency of utils, use kill: | |
| 274 # os.kill(active_test_data[1], signal.SIGTERM) | |
| 275 except OSError, e: | |
| 276 factory.log('Failed to kill test: ' + repr(e)) | |
| 261 | 277 |
| 262 def grab_shortcut_keys(kbd_shortcut_set, control_pid): | 278 def grab_shortcut_keys(kbd_shortcut_set, control_pid): |
| 263 disp = X_Display() | 279 disp = X_Display() |
| 264 root = disp.screen().root | 280 root = disp.screen().root |
| 265 | 281 |
| 266 # We want to receive KeyPress events | 282 # We want to receive KeyPress events |
| 267 root.change_attributes(event_mask = X.KeyPressMask) | 283 root.change_attributes(event_mask = X.KeyPressMask) |
| 268 | 284 |
| 269 keycode_map = {} | 285 keycode_map = {} |
| 270 for shortcut in kbd_shortcut_set: | 286 for shortcut in kbd_shortcut_set: |
| 271 keysym = gdk.keyval_from_name(shortcut) | 287 keysym = gdk.keyval_from_name(shortcut) |
| 272 keycode = disp.keysym_to_keycode(keysym) | 288 keycode = disp.keysym_to_keycode(keysym) |
| 273 keycode_map[keycode] = shortcut | 289 keycode_map[keycode] = shortcut |
| 274 root.grab_key(keycode, X.ControlMask, 1, | 290 root.grab_key(keycode, X.ControlMask, 1, |
| 275 X.GrabModeAsync, X.GrabModeAsync) | 291 X.GrabModeAsync, X.GrabModeAsync) |
| 276 | 292 |
| 277 # This flushes the XGrabKey calls to the server. | 293 # This flushes the XGrabKey calls to the server. |
| 278 for x in range(0, root.display.pending_events()): | 294 for x in range(0, root.display.pending_events()): |
| 279 root.display.next_event() | 295 root.display.next_event() |
| 280 | 296 |
| 281 def handle_xevent(src, cond, xhandle=root.display, | 297 def handle_xevent(src, cond, xhandle=root.display, |
| 282 keycode_map=keycode_map, | 298 keycode_map=keycode_map, |
| 283 control_pid=control_pid): | 299 control_pid=control_pid): |
| 284 for i in range(0, xhandle.pending_events()): | 300 for i in range(0, xhandle.pending_events()): |
| 285 xevent = xhandle.next_event() | 301 xevent = xhandle.next_event() |
| 286 if xevent.type == X.KeyPress: | 302 if xevent.type == X.KeyPress: |
| 287 keycode = xevent.detail | 303 keycode = xevent.detail |
| 288 factory.set_shared_data('activated_kbd_shortcut', | 304 factory.set_shared_data('activated_kbd_shortcut', |
| 289 keycode_map[keycode]) | 305 keycode_map[keycode]) |
| 290 os.kill(control_pid, signal.SIGUSR1) | 306 kill_active_test(control_pid) |
| 291 return True | 307 return True |
| 292 | 308 |
| 293 gobject.io_add_watch(root.display, gobject.IO_IN, handle_xevent) | 309 gobject.io_add_watch(root.display, gobject.IO_IN, handle_xevent) |
| 294 | 310 |
| 295 | 311 |
| 296 def main(test_list, status_file_path, control_pid): | 312 def main(test_list, status_file_path, control_pid): |
| 297 '''This process is launched by the autotest suite_Factory control | 313 '''This process is launched by the autotest suite_Factory control |
| 298 process, which should be identified by the <control pid> cmdline | 314 process, which should be identified by the <control pid> cmdline |
| 299 argument. When operators press keyboard shortcuts, the shortcut | 315 argument. When operators press keyboard shortcuts, the shortcut |
| 300 value is sent by set_shared_data() and a SIGUSR1 is sent to | 316 value is sent by set_shared_data() and a SIGUSR1 is sent to |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 380 | 396 |
| 381 if len(sys.argv) != 4: | 397 if len(sys.argv) != 4: |
| 382 print ('usage: %s <test list path> <status file path> <control pid>' % | 398 print ('usage: %s <test list path> <status file path> <control pid>' % |
| 383 sys.argv[0]) | 399 sys.argv[0]) |
| 384 test_list_path, status_file_path, control_pid_str = sys.argv[1:] | 400 test_list_path, status_file_path, control_pid_str = sys.argv[1:] |
| 385 control_pid = int(control_pid_str) | 401 control_pid = int(control_pid_str) |
| 386 | 402 |
| 387 execfile(test_list_path) | 403 execfile(test_list_path) |
| 388 | 404 |
| 389 main(TEST_LIST, status_file_path, control_pid) | 405 main(TEST_LIST, status_file_path, control_pid) |
| OLD | NEW |