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 17 matching lines...) Expand all Loading... |
28 import os | 28 import os |
29 import pango | 29 import pango |
30 import subprocess | 30 import subprocess |
31 import sys | 31 import sys |
32 import time | 32 import time |
33 | 33 |
34 | 34 |
35 def XXX_log(s): | 35 def XXX_log(s): |
36 print >> sys.stderr, '--- XXX : ' + s | 36 print >> sys.stderr, '--- XXX : ' + s |
37 | 37 |
| 38 _ACTIVE = 'ACTIVE' |
| 39 _PASSED = 'PASS' |
| 40 _FAILED = 'FAIL' |
| 41 _UNTESTED = 'UNTESTED' |
38 | 42 |
39 _LABEL_COLORS = { | 43 _LABEL_COLORS = { |
40 'active': gtk.gdk.color_parse('light goldenrod'), | 44 _ACTIVE: gtk.gdk.color_parse('light goldenrod'), |
41 'passed': gtk.gdk.color_parse('pale green'), | 45 _PASSED: gtk.gdk.color_parse('pale green'), |
42 'failed': gtk.gdk.color_parse('tomato'), | 46 _FAILED: gtk.gdk.color_parse('tomato'), |
43 'untested': gtk.gdk.color_parse('dark slate grey')} | 47 _UNTESTED: gtk.gdk.color_parse('dark slate grey')} |
44 | 48 |
45 _LABEL_EN_SIZE = (160, 35) | 49 _LABEL_EN_SIZE = (160, 35) |
46 _LABEL_EN_FONT = pango.FontDescription('courier new extra-condensed 16') | 50 _LABEL_EN_FONT = pango.FontDescription('courier new extra-condensed 16') |
47 _LABEL_ZW_SIZE = (70, 35) | 51 _LABEL_ZW_SIZE = (70, 35) |
48 _LABEL_ZW_FONT = pango.FontDescription('normal 12') | 52 _LABEL_ZW_FONT = pango.FontDescription('normal 12') |
49 _LABEL_T_SIZE = (30, 35) | 53 _LABEL_T_SIZE = (30, 35) |
50 _LABEL_T_FONT = pango.FontDescription('courier new italic ultra-condensed 10') | 54 _LABEL_T_FONT = pango.FontDescription('courier new italic ultra-condensed 10') |
51 _LABEL_UNTESTED_FG = gtk.gdk.color_parse('grey40') | 55 _LABEL_UNTESTED_FG = gtk.gdk.color_parse('grey40') |
52 _LABEL_TROUGH_COLOR = gtk.gdk.color_parse('grey20') | 56 _LABEL_TROUGH_COLOR = gtk.gdk.color_parse('grey20') |
| 57 _LABEL_STATUS_SIZE = (140, 30) |
| 58 _LABEL_STATUS_FONT = pango.FontDescription( |
| 59 'courier new bold extra-condensed 16') |
53 _SEP_COLOR = gtk.gdk.color_parse('grey50') | 60 _SEP_COLOR = gtk.gdk.color_parse('grey50') |
54 _BLACK = gtk.gdk.color_parse('black') | 61 _BLACK = gtk.gdk.color_parse('black') |
55 _LIGHT_GREEN = gtk.gdk.color_parse('light green') | 62 _LIGHT_GREEN = gtk.gdk.color_parse('light green') |
56 | 63 _OTHER_LABEL_FONT = pango.FontDescription('courier new condensed 20') |
57 | 64 |
58 class console_proc: | 65 class console_proc: |
59 '''Display a progress log. Implemented by launching an borderless | 66 '''Display a progress log. Implemented by launching an borderless |
60 xterm at a strategic location, and running tail against the log.''' | 67 xterm at a strategic location, and running tail against the log.''' |
61 | 68 |
62 def __init__(self, allocation, log_file_path): | 69 def __init__(self, allocation, log_file_path): |
63 xterm_coords = '135x14+%d+%d' % (allocation.x, allocation.y) | 70 xterm_coords = '135x14+%d+%d' % (allocation.x, allocation.y) |
64 XXX_log('xterm_coords = %s' % xterm_coords) | 71 XXX_log('xterm_coords = %s' % xterm_coords) |
65 xterm_cmd = ('xterm --geometry %s -bw 0 -e ' % xterm_coords + | 72 xterm_cmd = ('xterm --geometry %s -bw 0 -e ' % xterm_coords + |
66 'tail -f %s' % log_file_path) | 73 'tail -f %s' % log_file_path) |
(...skipping 13 matching lines...) Expand all Loading... |
80 gtk.main_quit() | 87 gtk.main_quit() |
81 return True | 88 return True |
82 | 89 |
83 def control_recv(): | 90 def control_recv(): |
84 return eval(sys.stdin.readline().rstrip()) | 91 return eval(sys.stdin.readline().rstrip()) |
85 | 92 |
86 def control_send(x): | 93 def control_send(x): |
87 print repr(x) | 94 print repr(x) |
88 sys.stdout.flush() | 95 sys.stdout.flush() |
89 | 96 |
| 97 def control_send_target_test_update(test): |
| 98 XXX_log('ui send_target_test_update %s.%s_%s' % |
| 99 (test.formal_name, test.tag_prefix, test.count)) |
| 100 control_send((test.formal_name, test.tag_prefix, test.count)) |
| 101 |
90 | 102 |
91 # Capture keyboard events here for debugging -- under normal | 103 # Capture keyboard events here for debugging -- under normal |
92 # circumstances, all keyboard events should be captured by executing | 104 # circumstances, all keyboard events should be captured by executing |
93 # tests, and hence this should not be called. | 105 # tests, and hence this should not be called. |
94 | 106 |
95 def handle_key_release_event(_, event): | 107 def handle_key_release_event(_, event): |
96 XXX_log('base ui key event (%s)' % event.keyval) | 108 XXX_log('base ui key event (%s)' % event.keyval) |
97 return True | 109 return True |
98 | 110 |
99 | 111 |
100 def update_label_status(test, status): | 112 class test_label_box(gtk.EventBox): |
101 if status != 'untested': | 113 |
102 test.label_box.modify_fg(gtk.STATE_NORMAL, _BLACK) | 114 def __init__(self, test): |
103 for label in test.label_list: | 115 gtk.EventBox.__init__(self) |
104 label.modify_fg(gtk.STATE_NORMAL, _BLACK) | 116 label_en = gtk.Label(test.label_en) |
105 test.label_box.modify_bg(gtk.STATE_NORMAL, _LABEL_COLORS[status]) | 117 label_en.set_size_request(*_LABEL_EN_SIZE) |
106 test.label_box.queue_draw() | 118 label_en.modify_font(_LABEL_EN_FONT) |
| 119 label_en.set_alignment(0.8, 0.5) |
| 120 label_en.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG) |
| 121 label_zw = gtk.Label(test.label_zw) |
| 122 label_zw.set_size_request(*_LABEL_ZW_SIZE) |
| 123 label_zw.modify_font(_LABEL_ZW_FONT) |
| 124 label_zw.set_alignment(0.2, 0.5) |
| 125 label_zw.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG) |
| 126 label_t = gtk.Label('C-' + test.trigger) |
| 127 label_t.set_size_request(*_LABEL_T_SIZE) |
| 128 label_t.modify_font(_LABEL_T_FONT) |
| 129 label_t.set_alignment(0.5, 0.5) |
| 130 label_t.modify_fg(gtk.STATE_NORMAL, _BLACK) |
| 131 hbox = gtk.HBox() |
| 132 hbox.pack_start(label_en, False, False) |
| 133 hbox.pack_start(label_zw, False, False) |
| 134 hbox.pack_start(label_t, False, False) |
| 135 self.add(hbox) |
| 136 self.label_list = [label_en, label_zw] |
| 137 |
| 138 def update_status(self, status): |
| 139 if status != _UNTESTED: |
| 140 self.modify_fg(gtk.STATE_NORMAL, _BLACK) |
| 141 for label in self.label_list: |
| 142 label.modify_fg(gtk.STATE_NORMAL, _BLACK) |
| 143 self.modify_bg(gtk.STATE_NORMAL, _LABEL_COLORS[status]) |
| 144 self.queue_draw() |
| 145 |
| 146 |
| 147 class subtest_label_box(gtk.EventBox): |
| 148 |
| 149 def __init__(self, test): |
| 150 gtk.EventBox.__init__(self) |
| 151 self.modify_bg(gtk.STATE_NORMAL, _BLACK) |
| 152 label_status = gtk.Label(_UNTESTED) |
| 153 label_status.set_size_request(*_LABEL_STATUS_SIZE) |
| 154 label_status.set_alignment(0, 0.5) |
| 155 label_status.modify_font(_LABEL_STATUS_FONT) |
| 156 label_status.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG) |
| 157 label_en = gtk.Label(test.label_en) |
| 158 label_en.set_alignment(1, 0.5) |
| 159 label_en.modify_font(_LABEL_EN_FONT) |
| 160 label_en.modify_fg(gtk.STATE_NORMAL, _LIGHT_GREEN) |
| 161 label_zw = gtk.Label(test.label_zw) |
| 162 label_zw.set_alignment(1, 0.5) |
| 163 label_zw.modify_font(_LABEL_ZW_FONT) |
| 164 label_zw.modify_fg(gtk.STATE_NORMAL, _LIGHT_GREEN) |
| 165 label_sep = gtk.Label(' : ') |
| 166 label_sep.set_alignment(0.5, 0.5) |
| 167 label_sep.modify_font(_LABEL_EN_FONT) |
| 168 label_sep.modify_fg(gtk.STATE_NORMAL, _LIGHT_GREEN) |
| 169 hbox = gtk.HBox() |
| 170 hbox.pack_end(label_status, False, False) |
| 171 hbox.pack_end(label_sep, False, False) |
| 172 hbox.pack_end(label_zw, False, False) |
| 173 hbox.pack_end(label_en, False, False) |
| 174 self.add(hbox) |
| 175 self.label_status = label_status |
| 176 |
| 177 def update_status(self, status): |
| 178 if status != _UNTESTED: |
| 179 self.label_status.set_text(status) |
| 180 self.label_status.modify_fg(gtk.STATE_NORMAL, _LABEL_COLORS[status]) |
| 181 self.queue_draw() |
| 182 |
| 183 |
| 184 class status_map(): |
| 185 |
| 186 def __init__(self): |
| 187 self.status_dict = {} |
| 188 |
| 189 def index(self, formal_name, tag_prefix): |
| 190 return '%s.%s' % (formal_name, tag_prefix) |
| 191 |
| 192 def lookup(self, formal_name, tag_prefix): |
| 193 return self.status_dict.setdefault( |
| 194 self.index(formal_name, tag_prefix), |
| 195 (_UNTESTED, 0)) |
| 196 |
| 197 def update(self, formal_name, tag_prefix, status, count): |
| 198 _, existing_count = self.lookup(formal_name, tag_prefix) |
| 199 if count > existing_count: |
| 200 index = self.index(formal_name, tag_prefix) |
| 201 self.status_dict[index] = (status, count) |
| 202 |
| 203 def get_subtest_status(self, test): |
| 204 map(self.set_test_status, test.automated_seq) |
| 205 sub_status_set = set(st.status for st in test.automated_seq) |
| 206 min_count = min([st.count for st in test.automated_seq]) |
| 207 max_count = max([st.count for st in test.automated_seq]) |
| 208 if len(sub_status_set) == 1: |
| 209 return (sub_status_set.pop(), max_count) |
| 210 if test.count > min_count: |
| 211 return (_ACTIVE, max_count) |
| 212 return (_FAILED, max_count) |
| 213 |
| 214 def set_test_status(self, test): |
| 215 status, count = ( |
| 216 test.automated_seq |
| 217 and self.get_subtest_status(test) |
| 218 or self.lookup(test.formal_name, test.tag_prefix)) |
| 219 status = test.count > count and _ACTIVE or status |
| 220 max_count = max(test.count, count) |
| 221 if test.status != status or test.count != max_count: |
| 222 XXX_log('status change for %s : %s/%s -> %s/%s' % |
| 223 (self.index(test.formal_name, test.tag_prefix), |
| 224 test.count, test.status, max_count, status)) |
| 225 test.status = status |
| 226 test.count = max_count |
| 227 test.label_box.update_status(status) |
107 | 228 |
108 | 229 |
109 def refresh_test_status(status_file_path, test_list): | 230 def refresh_test_status(status_file_path, test_list): |
110 result_dict = {} | 231 smap = status_map() |
111 with open(status_file_path) as file: | 232 with open(status_file_path) as file: |
112 for line in file: | 233 for line in file: |
113 columns = line.split('\t') | 234 columns = line.split('\t') |
114 if len(columns) >= 8 and not columns[0] and not columns[1]: | 235 if len(columns) >= 8 and not columns[0] and not columns[1]: |
115 result_state = columns[2] | 236 status = columns[2] == 'GOOD' and _PASSED or _FAILED |
116 full_name = columns[3] | 237 formal_name, _, tag = columns[3].rpartition('.') |
117 result_dict[full_name] = result_state | 238 tag_prefix, _, count = tag.rpartition('_') |
118 for test in test_list: | 239 count = int(count) |
119 full_name = '%s.%d' % (test.formal_name, test.count) | 240 smap.update(formal_name, tag_prefix, status, count) |
120 result_state = result_dict.get(full_name, None) | 241 map(smap.set_test_status, test_list) |
121 if result_state is None: | |
122 status = 'untested' | |
123 elif result_state == 'GOOD': | |
124 status = 'passed' | |
125 else: | |
126 status = 'failed' | |
127 if test.status != status: | |
128 XXX_log('status change for %s : %s -> %s' % | |
129 (test.label_en, test.status, status)) | |
130 test.status = status | |
131 update_label_status(test, status) | |
132 | 242 |
133 | 243 |
134 def select_active_test(test_list, remaining_tests_queue, | 244 def set_active_test(test): |
135 test_counters, trigger): | 245 test.count += 1 |
136 active_test = None | 246 test.label_box.update_status(_ACTIVE) |
137 if trigger is not None: | 247 control_send_target_test_update(test) |
138 trigger_dict = dict((test.trigger, test) for test in test_list) | |
139 active_test = trigger_dict.get(trigger, None) | |
140 if active_test in remaining_tests_queue: | |
141 remaining_tests_queue.remove(active_test) | |
142 if active_test is None: | |
143 active_test = remaining_tests_queue.pop() | |
144 count = test_counters[active_test.formal_name] | |
145 count += 1 | |
146 active_test.count = count | |
147 test_counters[active_test.formal_name] = count | |
148 update_label_status(active_test, 'active') | |
149 XXX_log('select_active_test %s.%d' % | |
150 (active_test.formal_name, active_test.count)) | |
151 return (active_test.label_en, active_test.count) | |
152 | |
153 | |
154 def make_test_label(test): | |
155 label_en = gtk.Label(test.label_en) | |
156 label_en.set_size_request(*_LABEL_EN_SIZE) | |
157 label_en.modify_font(_LABEL_EN_FONT) | |
158 label_en.set_alignment(0.8, 0.5) | |
159 label_en.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG) | |
160 label_zw = gtk.Label(test.label_zw) | |
161 label_zw.set_size_request(*_LABEL_ZW_SIZE) | |
162 label_zw.modify_font(_LABEL_ZW_FONT) | |
163 label_zw.set_alignment(0.2, 0.5) | |
164 label_zw.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG) | |
165 label_t = gtk.Label('C-' + test.trigger) | |
166 label_t.set_size_request(*_LABEL_T_SIZE) | |
167 label_t.modify_font(_LABEL_T_FONT) | |
168 label_t.set_alignment(0.5, 0.5) | |
169 label_t.modify_fg(gtk.STATE_NORMAL, _BLACK) | |
170 hbox = gtk.HBox() | |
171 hbox.pack_start(label_en, False, False) | |
172 hbox.pack_start(label_zw, False, False) | |
173 hbox.pack_start(label_t, False, False) | |
174 label_box = gtk.EventBox() | |
175 label_box.add(hbox) | |
176 test.label_box = label_box | |
177 test.label_list = [label_en, label_zw] | |
178 return label_box | |
179 | 248 |
180 | 249 |
181 def make_hsep(width=1): | 250 def make_hsep(width=1): |
182 frame = gtk.EventBox() | 251 frame = gtk.EventBox() |
183 frame.set_size_request(-1, width) | 252 frame.set_size_request(-1, width) |
184 frame.modify_bg(gtk.STATE_NORMAL, _SEP_COLOR) | 253 frame.modify_bg(gtk.STATE_NORMAL, _SEP_COLOR) |
185 return frame | 254 return frame |
186 | 255 |
187 | 256 |
188 def make_vsep(width=1): | 257 def make_vsep(width=1): |
189 frame = gtk.EventBox() | 258 frame = gtk.EventBox() |
190 frame.set_size_request(width, -1) | 259 frame.set_size_request(width, -1) |
191 frame.modify_bg(gtk.STATE_NORMAL, _SEP_COLOR) | 260 frame.modify_bg(gtk.STATE_NORMAL, _SEP_COLOR) |
192 return frame | 261 return frame |
193 | 262 |
194 | 263 |
195 def make_test_widget_box(): | 264 def make_notest_label(): |
196 label = gtk.Label('no active test') | 265 label = gtk.Label('no active test') |
197 font = pango.FontDescription('courier new condensed 20') | 266 label.modify_font(_OTHER_LABEL_FONT) |
198 label.modify_font(font) | |
199 label.set_alignment(0.5, 0.5) | 267 label.set_alignment(0.5, 0.5) |
200 label.modify_fg(gtk.STATE_NORMAL, _LIGHT_GREEN) | 268 label.modify_fg(gtk.STATE_NORMAL, _LIGHT_GREEN) |
201 box = gtk.EventBox() | 269 box = gtk.EventBox() |
202 box.modify_bg(gtk.STATE_NORMAL, _BLACK) | 270 box.modify_bg(gtk.STATE_NORMAL, _BLACK) |
203 box.add(label) | 271 box.add(label) |
204 align = gtk.Alignment(xalign=0.5, yalign=0.5) | 272 return box |
205 align.set_size_request(-1, -1) | 273 |
206 align.add(box) | 274 |
207 return align | 275 def make_automated_seq_widget(as_test): |
| 276 vbox = gtk.VBox() |
| 277 vbox.set_spacing(0) |
| 278 map(lambda st: vbox.pack_start(st.label_box, False, False), |
| 279 as_test.automated_seq) |
| 280 return vbox |
208 | 281 |
209 | 282 |
210 def main(): | 283 def main(): |
211 window = gtk.Window(gtk.WINDOW_TOPLEVEL) | 284 window = gtk.Window(gtk.WINDOW_TOPLEVEL) |
212 window.connect('destroy', lambda _: gtk.main_quit()) | 285 window.connect('destroy', lambda _: gtk.main_quit()) |
213 window.modify_bg(gtk.STATE_NORMAL, _BLACK) | 286 window.modify_bg(gtk.STATE_NORMAL, _BLACK) |
214 | 287 |
215 screen = window.get_screen() | 288 screen = window.get_screen() |
216 screen_size = (screen.get_width(), screen.get_height()) | 289 screen_size = (screen.get_width(), screen.get_height()) |
217 window.set_size_request(*screen_size) | 290 window.set_size_request(*screen_size) |
218 | 291 |
219 label_trough = gtk.VBox() | 292 label_trough = gtk.VBox() |
220 label_trough.set_spacing(0) | 293 label_trough.set_spacing(0) |
221 | 294 |
222 rhs_box = gtk.EventBox() | 295 rhs_box = gtk.EventBox() |
223 rhs_box.modify_bg(gtk.STATE_NORMAL, _LABEL_TROUGH_COLOR) | 296 rhs_box.modify_bg(gtk.STATE_NORMAL, _LABEL_TROUGH_COLOR) |
224 rhs_box.add(label_trough) | 297 rhs_box.add(label_trough) |
225 | 298 |
226 console_box = gtk.EventBox() | 299 console_box = gtk.EventBox() |
227 console_box.set_size_request(-1, 180) | 300 console_box.set_size_request(-1, 180) |
228 console_box.modify_bg(gtk.STATE_NORMAL, _BLACK) | 301 console_box.modify_bg(gtk.STATE_NORMAL, _BLACK) |
229 | 302 |
230 test_widget_box = make_test_widget_box() | 303 notest_label = make_notest_label() |
| 304 |
| 305 test_widget_box = gtk.Alignment(xalign=0.5, yalign=0.5) |
| 306 test_widget_box.set_size_request(-1, -1) |
| 307 test_widget_box.add(notest_label) |
231 | 308 |
232 lhs_box = gtk.VBox() | 309 lhs_box = gtk.VBox() |
233 lhs_box.pack_end(console_box, False, False) | 310 lhs_box.pack_end(console_box, False, False) |
234 lhs_box.pack_start(test_widget_box) | 311 lhs_box.pack_start(test_widget_box) |
235 lhs_box.pack_start(make_hsep(3), False, False) | 312 lhs_box.pack_start(make_hsep(3), False, False) |
236 | 313 |
237 base_box = gtk.HBox() | 314 base_box = gtk.HBox() |
238 base_box.pack_end(rhs_box, False, False) | 315 base_box.pack_end(rhs_box, False, False) |
239 base_box.pack_end(make_vsep(3), False, False) | 316 base_box.pack_end(make_vsep(3), False, False) |
240 base_box.pack_start(lhs_box) | 317 base_box.pack_start(lhs_box) |
241 | 318 |
242 window.connect('key-release-event', handle_key_release_event) | 319 window.connect('key-release-event', handle_key_release_event) |
243 window.add_events(gtk.gdk.KEY_RELEASE_MASK) | 320 window.add_events(gtk.gdk.KEY_RELEASE_MASK) |
244 | 321 |
245 # On startup, get general configuration data from the autotest | 322 # On startup, get general configuration data from the autotest |
246 # control program, specifically the list of tests to run (in | 323 # control program, specifically the list of tests to run (in |
247 # order) and some filenames. | 324 # order) and some filenames. |
248 XXX_log('pulling control info') | 325 XXX_log('pulling control info') |
249 test_list = control_recv() | 326 test_list = control_recv() |
250 status_file_path = control_recv() | 327 status_file_path = control_recv() |
251 log_file_path = control_recv() | 328 log_file_path = control_recv() |
252 | 329 |
253 for test in test_list: | 330 for test in test_list: |
254 test.status = None | 331 test.status = None |
255 label = make_test_label(test) | 332 test.count = 0 |
256 label_trough.pack_start(label, False, False) | 333 test.tag_prefix = test.trigger |
| 334 test.label_box = test_label_box(test) |
| 335 for subtest in test.automated_seq: |
| 336 subtest.status = None |
| 337 subtest.count = 0 |
| 338 subtest.tag_prefix = test.formal_name |
| 339 subtest.label_box = subtest_label_box(subtest) |
| 340 label_trough.pack_start(test.label_box, False, False) |
257 label_trough.pack_start(make_hsep(), False, False) | 341 label_trough.pack_start(make_hsep(), False, False) |
258 | 342 |
259 window.add(base_box) | 343 window.add(base_box) |
260 window.show_all() | 344 window.show_all() |
261 | 345 |
262 test_widget_allocation = test_widget_box.get_allocation() | 346 test_widget_allocation = test_widget_box.get_allocation() |
263 test_widget_size = (test_widget_allocation.width, | 347 test_widget_size = (test_widget_allocation.width, |
264 test_widget_allocation.height) | 348 test_widget_allocation.height) |
265 XXX_log('test_widget_size = %s' % repr(test_widget_size)) | 349 XXX_log('test_widget_size = %s' % repr(test_widget_size)) |
266 control_send(test_widget_size) | 350 control_send(test_widget_size) |
267 | 351 |
268 # Use a common datastructure for counters to allow multiple tests | 352 trigger_dict = dict((test.trigger, test) for test in test_list) |
269 # to share the same formal name. | |
270 test_counters = dict((test.formal_name, 0) for test in test_list) | |
271 for test in test_list: | |
272 test.count = 0 | |
273 | 353 |
274 refresh_test_status(status_file_path, test_list) | 354 refresh_test_status(status_file_path, test_list) |
275 remaining_tests_queue = [x for x in reversed(test_list) | 355 remaining_tests_queue = [x for x in reversed(test_list) |
276 if test.status != 'passed'] | 356 if x.status == _UNTESTED] |
| 357 XXX_log('remaining_tests_queue = %s' % |
| 358 repr([x.label_en for x in remaining_tests_queue])) |
| 359 |
| 360 active_test = None |
277 | 361 |
278 gobject.io_add_watch(sys.stdin, gobject.IO_IN, stdin_callback) | 362 gobject.io_add_watch(sys.stdin, gobject.IO_IN, stdin_callback) |
279 | 363 |
280 console = console_proc(console_box.get_allocation(), log_file_path) | 364 console = console_proc(console_box.get_allocation(), log_file_path) |
281 | 365 |
282 XXX_log('finished ui setup') | 366 XXX_log('finished ui setup') |
283 | 367 |
284 # Test selection is driven either by triggers or by the | 368 # Test selection is driven either by triggers or by the |
285 # remaining_tests_queue. If a trigger was seen, explicitly run | 369 # remaining_tests_queue. If a trigger was seen, explicitly run |
286 # the corresponding test. Otherwise choose the next test from the | 370 # the corresponding test. Otherwise choose the next test from the |
287 # queue. Tests are removed from the queue as they are run, | 371 # queue. Tests are removed from the queue as they are run, |
288 # regarless of the outcome. Tests that are interrupted by trigger | 372 # regarless of the outcome. Tests that are interrupted by trigger |
289 # are treated as having failed. | 373 # are treated as having failed. |
290 # | 374 # |
291 # Iterations in the main loop here are driven by data availability | 375 # Iterations in the main loop here are driven by data availability |
292 # on stdin, which is used to communicate with the autotest control | 376 # on stdin, which is used to communicate with the autotest control |
293 # program. On each step through the loop, a trigger is received | 377 # program. On each step through the loop, a trigger is received |
294 # (possibly None) to indicate how the next test should be selected. | 378 # (possibly None) to indicate how the next test should be selected. |
295 | 379 |
296 while remaining_tests_queue: | 380 while remaining_tests_queue: |
297 trigger = control_recv() | 381 command, arg = control_recv() |
298 XXX_log('ui received trigger (%s)' % trigger) | 382 XXX_log('ui received command %s(%s)' % (command, arg)) |
299 active_test_name, count = select_active_test( | 383 if command == 'switch_to': |
300 test_list, remaining_tests_queue, | 384 active_test = trigger_dict.get(arg, None) |
301 test_counters, trigger) | 385 if active_test in remaining_tests_queue: |
302 control_send((active_test_name, count)) | 386 remaining_tests_queue.remove(active_test) |
303 gtk.main() | 387 set_active_test(active_test) |
304 refresh_test_status(status_file_path, test_list) | 388 elif command == 'next_test': |
| 389 active_test = remaining_tests_queue.pop() |
| 390 set_active_test(active_test) |
| 391 else: |
| 392 XXX_log('ui command unknown, exiting...') |
| 393 break |
| 394 if active_test.automated_seq: |
| 395 XXX_log('ui starting automated_seq') |
| 396 subtest_queue = [x for x in reversed(active_test.automated_seq)] |
| 397 test_widget_box.remove(notest_label) |
| 398 as_widget = make_automated_seq_widget(active_test) |
| 399 test_widget_box.add(as_widget) |
| 400 window.show_all() |
| 401 command = None |
| 402 while command != 'quit_automated_seq': |
| 403 active_subtest = subtest_queue.pop() |
| 404 active_subtest.label_box.update_status(_ACTIVE) |
| 405 gtk.main() |
| 406 command = control_recv() |
| 407 XXX_log('ui automated_seq step (%s)' % command) |
| 408 refresh_test_status(status_file_path, test_list) |
| 409 test_widget_box.queue_draw() |
| 410 test_widget_box.remove(as_widget) |
| 411 test_widget_box.add(notest_label) |
| 412 window.show_all() |
| 413 XXX_log('ui exiting automated_seq') |
| 414 else: |
| 415 gtk.main() |
| 416 refresh_test_status(status_file_path, test_list) |
305 | 417 |
| 418 # Tell the control process we are done. |
306 control_send((None, 0)) | 419 control_send((None, 0)) |
307 | 420 |
308 XXX_log('exiting ui') | 421 XXX_log('exiting ui') |
309 | 422 |
310 if __name__ == '__main__': | 423 if __name__ == '__main__': |
311 | 424 |
312 # In global scope, get the test_data class description from the | 425 # In global scope, get the test_data class description from the |
313 # control program -- this allows a convenient single point of | 426 # control program -- this allows a convenient single point of |
314 # definition for this class. | 427 # definition for this class. |
315 test_data_class_def = control_recv() | 428 test_data_class_def = control_recv() |
316 exec(test_data_class_def) | 429 exec(test_data_class_def) |
317 | 430 |
318 main() | 431 main() |
OLD | NEW |