| 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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 def update(self, status): | 156 def update(self, status): |
| 157 if status == ful.UNTESTED: | 157 if status == ful.UNTESTED: |
| 158 return | 158 return |
| 159 self.label_status.set_text(status) | 159 self.label_status.set_text(status) |
| 160 self.label_status.modify_fg(gtk.STATE_NORMAL, ful.LABEL_COLORS[status]) | 160 self.label_status.modify_fg(gtk.STATE_NORMAL, ful.LABEL_COLORS[status]) |
| 161 self.queue_draw() | 161 self.queue_draw() |
| 162 | 162 |
| 163 | 163 |
| 164 class UiState(): | 164 class UiState(): |
| 165 | 165 |
| 166 def __init__(self, status_map, test_widget_box): | 166 def __init__(self, test_widget_box, automated_sequence_set): |
| 167 | 167 |
| 168 def make_empty_test_label_widget(): | 168 def make_empty_test_label_widget(): |
| 169 label_box = gtk.EventBox() | 169 label_box = gtk.EventBox() |
| 170 label_box.modify_bg(gtk.STATE_NORMAL, ful.BLACK) | 170 label_box.modify_bg(gtk.STATE_NORMAL, ful.BLACK) |
| 171 label = ful.make_label('no active test', font=_OTHER_LABEL_FONT, | 171 label = ful.make_label('no active test', font=_OTHER_LABEL_FONT, |
| 172 alignment=(0.5, 0.5)) | 172 alignment=(0.5, 0.5)) |
| 173 label_box.add(label) | 173 label_box.add(label) |
| 174 return label_box | 174 return label_box |
| 175 | 175 |
| 176 def make_automated_seq_label_widget(subtest_list): | 176 def make_automated_sequence_label_widget(subtest_list): |
| 177 vbox = gtk.VBox() | 177 vbox = gtk.VBox() |
| 178 vbox.set_spacing(0) | 178 vbox.set_spacing(0) |
| 179 for subtest in subtest_list: | 179 for subtest in subtest_list: |
| 180 label_box = SubTestLabelBox(subtest) | 180 label_box = SubTestLabelBox(subtest) |
| 181 status_map.set_label_box(subtest, label_box) | 181 self.set_label_box(subtest, label_box) |
| 182 vbox.pack_start(status_map.lookup_label_box(subtest), | 182 vbox.pack_start(label_box, False, False) |
| 183 False, False) | |
| 184 return vbox | 183 return vbox |
| 185 | 184 |
| 186 self._status_map = status_map | 185 self._label_box_map = {} |
| 187 self._test_widget_box = test_widget_box | 186 self._test_widget_box = test_widget_box |
| 188 self._empty_test_widget = make_empty_test_label_widget() | 187 self._empty_test_widget = make_empty_test_label_widget() |
| 189 self._active_test_widget = self._empty_test_widget | 188 self._active_test_widget = self._empty_test_widget |
| 190 self.active_test = None | 189 self.active_test = None |
| 191 | 190 |
| 192 self._test_widget_box.add(self._empty_test_widget) | 191 self._test_widget_box.add(self._empty_test_widget) |
| 193 | 192 |
| 194 self._automated_seq_widget_map = dict( | 193 self._automated_seq_widget_map = dict( |
| 195 (t, make_automated_seq_label_widget(t.subtest_list)) | 194 (test, make_automated_sequence_label_widget(test.subtest_list)) |
| 196 for t in self._status_map.test_db.seq_test_set) | 195 for test in automated_sequence_set) |
| 197 | 196 |
| 198 def set_active_test(self, test): | 197 def status_change_callback(self, test, status): |
| 198 label_box = self._label_box_map.get(test) |
| 199 if label_box: |
| 200 label_box.update(status) |
| 201 |
| 202 def set_label_box(self, test, label_box): |
| 203 self._label_box_map[test] = label_box |
| 204 |
| 205 def set_active_test(self, test_db, test): |
| 199 '''Control what kind of widget is shown in the testing area of | 206 '''Control what kind of widget is shown in the testing area of |
| 200 the screen. For normal operator tests, this is just a label | 207 the screen. For normal operator tests, this is just a label |
| 201 saying there is no active test. The expectation is that the | 208 saying there is no active test. The expectation is that the |
| 202 operator test itself has a window obscuring this message. For | 209 operator test itself has a window obscuring this message. For |
| 203 automated sequences, since there is no other window, the no | 210 automated sequences, since there is no other window, the no |
| 204 active test message is replaced with an updated list of | 211 active test message is replaced with an updated list of |
| 205 subtest status.''' | 212 subtest status.''' |
| 206 if test is None or test == self.active_test: | 213 if test is None or test == self.active_test: |
| 207 return | 214 return |
| 208 factory.log('UI active test -> %s' % | 215 factory.log('UI active test is %s' % test_db.get_unique_id_str(test)) |
| 209 self._status_map.test_db.get_unique_details(test)) | |
| 210 self.active_test = test | 216 self.active_test = test |
| 211 self._test_widget_box.remove(self._active_test_widget) | 217 self._test_widget_box.remove(self._active_test_widget) |
| 212 active_widget = (test in self._status_map.test_db.seq_test_set | 218 active_widget = (isinstance(test, factory.AutomatedSequence) |
| 213 and self._automated_seq_widget_map[test] | 219 and self._automated_seq_widget_map[test] |
| 214 or self._empty_test_widget) | 220 or self._empty_test_widget) |
| 215 self._test_widget_box.add(active_widget) | 221 self._test_widget_box.add(active_widget) |
| 216 self._active_test_widget = active_widget | 222 self._active_test_widget = active_widget |
| 217 self._test_widget_box.show_all() | 223 self._test_widget_box.show_all() |
| 218 | 224 |
| 219 | 225 |
| 220 def refresh_status(status_map, ui_state): | 226 def refresh_status(status_map, test_db, ui_state): |
| 221 status_map.read_new_data() | 227 status_map.read_new_data() |
| 222 active_test = status_map.get_active_top_level_test() | 228 active_test = status_map.get_active_top_level_test() |
| 223 ui_state.set_active_test(active_test) | 229 ui_state.set_active_test(test_db, active_test) |
| 224 return True | 230 return True |
| 225 | 231 |
| 226 | 232 |
| 227 def grab_shortcut_keys(kbd_shortcut_set, control_pid): | 233 def grab_shortcut_keys(kbd_shortcut_set, control_pid): |
| 228 disp = X_Display() | 234 disp = X_Display() |
| 229 root = disp.screen().root | 235 root = disp.screen().root |
| 230 | 236 |
| 231 # We want to receive KeyPress events | 237 # We want to receive KeyPress events |
| 232 root.change_attributes(event_mask = X.KeyPressMask) | 238 root.change_attributes(event_mask = X.KeyPressMask) |
| 233 | 239 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 258 gobject.io_add_watch(root.display, gobject.IO_IN, handle_xevent) | 264 gobject.io_add_watch(root.display, gobject.IO_IN, handle_xevent) |
| 259 | 265 |
| 260 | 266 |
| 261 def main(test_list, status_file_path, control_pid): | 267 def main(test_list, status_file_path, control_pid): |
| 262 '''This process is launched by the autotest suite_Factory control | 268 '''This process is launched by the autotest suite_Factory control |
| 263 process, which should be identified by the <control pid> cmdline | 269 process, which should be identified by the <control pid> cmdline |
| 264 argument. When operators press keyboard shortcuts, the shortcut | 270 argument. When operators press keyboard shortcuts, the shortcut |
| 265 value is logged with log_shared_data() and a SIGUSR1 is sent to | 271 value is logged with log_shared_data() and a SIGUSR1 is sent to |
| 266 the control program.''' | 272 the control program.''' |
| 267 | 273 |
| 268 status_map = factory.StatusMap(test_list, status_file_path) | 274 test_db = factory.TestDatabase(test_list) |
| 269 | 275 |
| 270 window = gtk.Window(gtk.WINDOW_TOPLEVEL) | 276 window = gtk.Window(gtk.WINDOW_TOPLEVEL) |
| 271 window.connect('destroy', lambda _: gtk.main_quit()) | 277 window.connect('destroy', lambda _: gtk.main_quit()) |
| 272 window.modify_bg(gtk.STATE_NORMAL, ful.BLACK) | 278 window.modify_bg(gtk.STATE_NORMAL, ful.BLACK) |
| 273 | 279 |
| 274 screen = window.get_screen() | 280 screen = window.get_screen() |
| 275 if (screen is None): | 281 if (screen is None): |
| 276 log('ERROR: communication with the X server is not working, ' + | 282 log('ERROR: communication with the X server is not working, ' + |
| 277 'could not find a working screen. UI exiting.') | 283 'could not find a working screen. UI exiting.') |
| 278 sys.exit(1) | 284 sys.exit(1) |
| 279 | 285 |
| 280 screen_size = (screen.get_width(), screen.get_height()) | 286 screen_size = (screen.get_width(), screen.get_height()) |
| 281 window.set_size_request(*screen_size) | 287 window.set_size_request(*screen_size) |
| 282 | 288 |
| 283 label_trough = gtk.VBox() | 289 label_trough = gtk.VBox() |
| 284 label_trough.set_spacing(0) | 290 label_trough.set_spacing(0) |
| 285 | 291 |
| 286 rhs_box = gtk.EventBox() | 292 rhs_box = gtk.EventBox() |
| 287 rhs_box.modify_bg(gtk.STATE_NORMAL, _LABEL_TROUGH_COLOR) | 293 rhs_box.modify_bg(gtk.STATE_NORMAL, _LABEL_TROUGH_COLOR) |
| 288 rhs_box.add(label_trough) | 294 rhs_box.add(label_trough) |
| 289 | 295 |
| 290 console_box = gtk.EventBox() | 296 console_box = gtk.EventBox() |
| 291 console_box.set_size_request(-1, 180) | 297 console_box.set_size_request(-1, 180) |
| 292 console_box.modify_bg(gtk.STATE_NORMAL, ful.BLACK) | 298 console_box.modify_bg(gtk.STATE_NORMAL, ful.BLACK) |
| 293 | 299 |
| 294 test_widget_box = gtk.Alignment(xalign=0.5, yalign=0.5) | 300 test_widget_box = gtk.Alignment(xalign=0.5, yalign=0.5) |
| 295 test_widget_box.set_size_request(-1, -1) | 301 test_widget_box.set_size_request(-1, -1) |
| 296 | 302 |
| 297 ui_state = UiState(status_map, test_widget_box) | |
| 298 | |
| 299 lhs_box = gtk.VBox() | 303 lhs_box = gtk.VBox() |
| 300 lhs_box.pack_end(console_box, False, False) | 304 lhs_box.pack_end(console_box, False, False) |
| 301 lhs_box.pack_start(test_widget_box) | 305 lhs_box.pack_start(test_widget_box) |
| 302 lhs_box.pack_start(ful.make_hsep(3), False, False) | 306 lhs_box.pack_start(ful.make_hsep(3), False, False) |
| 303 | 307 |
| 304 base_box = gtk.HBox() | 308 base_box = gtk.HBox() |
| 305 base_box.pack_end(rhs_box, False, False) | 309 base_box.pack_end(rhs_box, False, False) |
| 306 base_box.pack_end(ful.make_vsep(3), False, False) | 310 base_box.pack_end(ful.make_vsep(3), False, False) |
| 307 base_box.pack_start(lhs_box) | 311 base_box.pack_start(lhs_box) |
| 308 | 312 |
| 309 window.connect('key-release-event', handle_key_release_event) | 313 window.connect('key-release-event', handle_key_release_event) |
| 310 window.add_events(gtk.gdk.KEY_RELEASE_MASK) | 314 window.add_events(gtk.gdk.KEY_RELEASE_MASK) |
| 311 | 315 |
| 312 gobject.timeout_add(_STATUS_REFRESH_MS, refresh_status, | 316 ui_state = UiState(test_widget_box, test_db.get_automated_sequences()) |
| 313 status_map, ui_state) | |
| 314 | 317 |
| 315 for test in test_list: | 318 for test in test_list: |
| 316 label_box = TestLabelBox(test) | 319 label_box = TestLabelBox(test) |
| 317 status_map.set_label_box(test, label_box) | 320 ui_state.set_label_box(test, label_box) |
| 318 label_trough.pack_start(label_box, False, False) | 321 label_trough.pack_start(label_box, False, False) |
| 319 label_trough.pack_start(ful.make_hsep(), False, False) | 322 label_trough.pack_start(ful.make_hsep(), False, False) |
| 320 | 323 |
| 321 window.add(base_box) | 324 window.add(base_box) |
| 322 window.show_all() | 325 window.show_all() |
| 323 | 326 |
| 324 grab_shortcut_keys(status_map.test_db.kbd_shortcut_set, control_pid) | 327 status_map = factory.StatusMap( |
| 328 test_list, status_file_path, test_db=test_db, |
| 329 status_change_callback=ui_state.status_change_callback) |
| 330 |
| 331 gobject.timeout_add(_STATUS_REFRESH_MS, refresh_status, |
| 332 status_map, test_db, ui_state) |
| 333 |
| 334 kbd_shortcut_db = factory.KbdShortcutDatabase(test_list, test_db) |
| 335 grab_shortcut_keys(kbd_shortcut_db.get_shortcut_keys(), control_pid) |
| 325 | 336 |
| 326 ful.hide_cursor(window.window) | 337 ful.hide_cursor(window.window) |
| 327 | 338 |
| 328 test_widget_allocation = test_widget_box.get_allocation() | 339 test_widget_allocation = test_widget_box.get_allocation() |
| 329 test_widget_size = (test_widget_allocation.width, | 340 test_widget_size = (test_widget_allocation.width, |
| 330 test_widget_allocation.height) | 341 test_widget_allocation.height) |
| 331 factory.log_shared_data('test_widget_size', test_widget_size) | 342 factory.log_shared_data('test_widget_size', test_widget_size) |
| 332 | 343 |
| 333 console = Console(console_box.get_allocation()) | 344 console = Console(console_box.get_allocation()) |
| 334 | 345 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 345 | 356 |
| 346 if len(sys.argv) != 4: | 357 if len(sys.argv) != 4: |
| 347 print ('usage: %s <test list path> <status file path> <control pid>' % | 358 print ('usage: %s <test list path> <status file path> <control pid>' % |
| 348 sys.argv[0]) | 359 sys.argv[0]) |
| 349 test_list_path, status_file_path, control_pid_str = sys.argv[1:] | 360 test_list_path, status_file_path, control_pid_str = sys.argv[1:] |
| 350 control_pid = int(control_pid_str) | 361 control_pid = int(control_pid_str) |
| 351 | 362 |
| 352 execfile(test_list_path) | 363 execfile(test_list_path) |
| 353 | 364 |
| 354 main(TEST_LIST, status_file_path, control_pid) | 365 main(TEST_LIST, status_file_path, control_pid) |
| OLD | NEW |