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

Side by Side Diff: client/bin/factory_ui

Issue 2836043: Relocate library files for wider access and re-use; also associated cleanup. (Closed) Base URL: ssh://gitrw.chromium.org/autotest.git
Patch Set: patch typo Created 10 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
« no previous file with comments | « client/bin/factory.py ('k') | client/bin/factory_ui_lib.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 # provide factory operators feedback on test status and control over 11 # provide factory operators feedback on test status and control over
12 # execution order. 12 # execution order.
13 # 13 #
14 # In short, the UI is composed of a 'console' panel on the bottom of 14 # In short, the UI is composed of a 'console' panel on the bottom of
15 # the screen which displays the autotest log, and there is also a 15 # the screen which displays the autotest log, and there is also a
16 # 'test list' panel on the right hand side of the screen. The 16 # 'test list' panel on the right hand side of the screen. The
17 # majority of the screen is dedicated to tests, which are executed in 17 # majority of the screen is dedicated to tests, which are executed in
18 # seperate processes, but instructed to display their own UIs in this 18 # seperate processes, but instructed to display their own UIs in this
19 # dedicated area whenever possible. Tests in the test list are 19 # dedicated area whenever possible. Tests in the test list are
20 # executed in order by default, but can be activated on demand via 20 # executed in order by default, but can be activated on demand via
21 # associated keyboard shortcuts (triggers). As tests are run, their 21 # associated keyboard shortcuts (triggers). As tests are run, their
22 # status is color-indicated to the operator -- greyed out means 22 # status is color-indicated to the operator -- greyed out means
23 # untested, yellow means active, green passed and red failed. 23 # untested, yellow means active, green passed and red failed.
24 24
25 25
26 import gobject 26 import gobject
27 import gtk 27 import gtk
28 import imp
28 import os 29 import os
29 import pango 30 import pango
30 import subprocess 31 import subprocess
31 import sys 32 import sys
32 import time 33 import time
33 34
35 import common
36 import factory
37 import factory_ui_lib as ful
34 38
35 def XXX_log(s): 39 from factory import TestData
36 print >> sys.stderr, 'FACTORY: ' + s
37 40
38 _ACTIVE = 'ACTIVE'
39 _PASSED = 'PASS'
40 _FAILED = 'FAIL'
41 _UNTESTED = 'UNTESTED'
42 41
43 _STATUS_CODE_MAP = { 42 _SEP_COLOR = gtk.gdk.color_parse('grey50')
44 'START': _ACTIVE,
45 'GOOD': _PASSED,
46 'FAIL': _FAILED,
47 'ERROR': _FAILED}
48
49 _LABEL_COLORS = {
50 _ACTIVE: gtk.gdk.color_parse('light goldenrod'),
51 _PASSED: gtk.gdk.color_parse('pale green'),
52 _FAILED: gtk.gdk.color_parse('tomato'),
53 _UNTESTED: gtk.gdk.color_parse('dark slate grey')}
54 43
55 _LABEL_EN_SIZE = (160, 35) 44 _LABEL_EN_SIZE = (160, 35)
56 _LABEL_EN_FONT = pango.FontDescription('courier new extra-condensed 16') 45 _LABEL_EN_FONT = pango.FontDescription('courier new extra-condensed 16')
57 _LABEL_ZW_SIZE = (70, 35) 46 _LABEL_ZW_SIZE = (70, 35)
58 _LABEL_ZW_FONT = pango.FontDescription('normal 12') 47 _LABEL_ZW_FONT = pango.FontDescription('normal 12')
59 _LABEL_T_SIZE = (30, 35) 48 _LABEL_T_SIZE = (30, 35)
60 _LABEL_T_FONT = pango.FontDescription('courier new italic ultra-condensed 10') 49 _LABEL_T_FONT = pango.FontDescription('courier new italic ultra-condensed 10')
61 _LABEL_UNTESTED_FG = gtk.gdk.color_parse('grey40') 50 _LABEL_UNTESTED_FG = gtk.gdk.color_parse('grey40')
62 _LABEL_TROUGH_COLOR = gtk.gdk.color_parse('grey20') 51 _LABEL_TROUGH_COLOR = gtk.gdk.color_parse('grey20')
63 _LABEL_STATUS_SIZE = (140, 30) 52 _LABEL_STATUS_SIZE = (140, 30)
64 _LABEL_STATUS_FONT = pango.FontDescription( 53 _LABEL_STATUS_FONT = pango.FontDescription(
65 'courier new bold extra-condensed 16') 54 'courier new bold extra-condensed 16')
66 _SEP_COLOR = gtk.gdk.color_parse('grey50')
67 _BLACK = gtk.gdk.color_parse('black')
68 _LIGHT_GREEN = gtk.gdk.color_parse('light green')
69 _OTHER_LABEL_FONT = pango.FontDescription('courier new condensed 20') 55 _OTHER_LABEL_FONT = pango.FontDescription('courier new condensed 20')
70 56
71 class console_proc: 57
58 class Console:
72 '''Display a progress log. Implemented by launching an borderless 59 '''Display a progress log. Implemented by launching an borderless
73 xterm at a strategic location, and running tail against the log.''' 60 xterm at a strategic location, and running tail against the log.'''
74 61
75 def __init__(self, allocation, log_file_path): 62 def __init__(self, allocation):
76 xterm_coords = '135x14+%d+%d' % (allocation.x, allocation.y) 63 xterm_coords = '135x14+%d+%d' % (allocation.x, allocation.y)
77 XXX_log('xterm_coords = %s' % xterm_coords) 64 factory.log('xterm_coords = %s' % xterm_coords)
78 xterm_cmd = (('aterm --geometry %s -bw 0 -e bash -c ' % 65 xterm_cmd = (('aterm --geometry %s -bw 0 -e bash -c ' %
79 xterm_coords).split() + 66 xterm_coords).split() +
80 ['tail -f %s | grep FACTORY' % log_file_path]) 67 ['tail -f %s | grep FACTORY' % factory.LOG_PATH])
81 XXX_log('xterm_cmd = %s' % xterm_cmd) 68 factory.log('xterm_cmd = %s' % xterm_cmd)
82 self._proc = subprocess.Popen(xterm_cmd) 69 self._proc = subprocess.Popen(xterm_cmd)
83 70
84 def __del__(self): 71 def __del__(self):
85 XXX_log('console_proc __del__') 72 factory.log('console_proc __del__')
86 self._proc.kill() 73 self._proc.kill()
87 74
88 75
89 # Routines to communicate with the autotest control file, using python 76 # Routines to communicate with the autotest control file, using python
90 # expressions. The stdin_callback assures notification for any new 77 # expressions. The stdin_callback assures notification for any new
91 # messages. 78 # messages.
92 79
93 def stdin_callback(s, c): 80 def stdin_callback(s, c):
94 XXX_log('stdin_callback, quitting gtk main') 81 factory.log('stdin_callback, quitting gtk main')
95 gtk.main_quit() 82 gtk.main_quit()
96 return True 83 return True
97 84
98 def control_recv(): 85 def control_recv():
99 return eval(sys.stdin.readline().rstrip()) 86 return eval(sys.stdin.readline().rstrip())
100 87
101 def control_send(x): 88 def control_send(x):
102 print repr(x) 89 print repr(x)
103 sys.stdout.flush() 90 sys.stdout.flush()
104 91
105 def control_send_target_test_update(test, count): 92 def control_send_target_test_update(test, count):
106 XXX_log('ui send_target_test_update %s.%s_%s' % 93 factory.log('ui send_target_test_update %s.%s_%s' %
107 (test.formal_name, test.tag_prefix, count)) 94 (test.formal_name, test.tag_prefix, count))
108 control_send((test.formal_name, test.tag_prefix, count)) 95 control_send((test.formal_name, test.tag_prefix, count))
109 96
110 97
111 # Capture keyboard events here for debugging -- under normal 98 # Capture keyboard events here for debugging -- under normal
112 # circumstances, all keyboard events should be captured by executing 99 # circumstances, all keyboard events should be captured by executing
113 # tests, and hence this should not be called. 100 # tests, and hence this should not be called.
114 101
115 def handle_key_release_event(_, event): 102 def handle_key_release_event(_, event):
116 XXX_log('base ui key event (%s)' % event.keyval) 103 factory.log('base ui key event (%s)' % event.keyval)
117 return True 104 return True
118 105
119 106
120 class TestLabelBox(gtk.EventBox): 107 class TestLabelBox(gtk.EventBox):
121 108
122 def __init__(self, test): 109 def __init__(self, test):
123 gtk.EventBox.__init__(self) 110 gtk.EventBox.__init__(self)
124 self.modify_bg(gtk.STATE_NORMAL, _LABEL_COLORS[_UNTESTED]) 111 self.modify_bg(gtk.STATE_NORMAL, ft.LABEL_COLORS[ft.UNTESTED])
125 label_en = gtk.Label(test.label_en) 112 label_en = gtk.Label(test.label_en)
126 label_en.set_size_request(*_LABEL_EN_SIZE) 113 label_en.set_size_request(*_LABEL_EN_SIZE)
127 label_en.modify_font(_LABEL_EN_FONT) 114 label_en.modify_font(_LABEL_EN_FONT)
128 label_en.set_alignment(0.5, 0.5) 115 label_en.set_alignment(0.5, 0.5)
129 label_en.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG) 116 label_en.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG)
130 label_zw = gtk.Label(test.label_zw) 117 label_zw = gtk.Label(test.label_zw)
131 label_zw.set_size_request(*_LABEL_ZW_SIZE) 118 label_zw.set_size_request(*_LABEL_ZW_SIZE)
132 label_zw.modify_font(_LABEL_ZW_FONT) 119 label_zw.modify_font(_LABEL_ZW_FONT)
133 label_zw.set_alignment(0.5, 0.5) 120 label_zw.set_alignment(0.5, 0.5)
134 label_zw.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG) 121 label_zw.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG)
135 label_t = gtk.Label('C-' + test.trigger) 122 label_t = gtk.Label('C-' + test.trigger)
136 label_t.set_size_request(*_LABEL_T_SIZE) 123 label_t.set_size_request(*_LABEL_T_SIZE)
137 label_t.modify_font(_LABEL_T_FONT) 124 label_t.modify_font(_LABEL_T_FONT)
138 label_t.set_alignment(0.5, 0.5) 125 label_t.set_alignment(0.5, 0.5)
139 label_t.modify_fg(gtk.STATE_NORMAL, _BLACK) 126 label_t.modify_fg(gtk.STATE_NORMAL, ft.BLACK)
140 hbox = gtk.HBox() 127 hbox = gtk.HBox()
141 hbox.pack_start(label_en, False, False) 128 hbox.pack_start(label_en, False, False)
142 hbox.pack_start(label_zw, False, False) 129 hbox.pack_start(label_zw, False, False)
143 hbox.pack_start(label_t, False, False) 130 hbox.pack_start(label_t, False, False)
144 self.add(hbox) 131 self.add(hbox)
145 self.label_list = [label_en, label_zw] 132 self.label_list = [label_en, label_zw]
146 133
147 def update(self, status): 134 def update(self, status):
148 if status == _UNTESTED: 135 if status == ft.UNTESTED:
149 return 136 return
150 self.modify_fg(gtk.STATE_NORMAL, _BLACK) 137 self.modify_fg(gtk.STATE_NORMAL, ft.BLACK)
151 for label in self.label_list: 138 for label in self.label_list:
152 label.modify_fg(gtk.STATE_NORMAL, _BLACK) 139 label.modify_fg(gtk.STATE_NORMAL, ft.BLACK)
153 self.modify_bg(gtk.STATE_NORMAL, _LABEL_COLORS[status]) 140 self.modify_bg(gtk.STATE_NORMAL, ft.LABEL_COLORS[status])
154 self.queue_draw() 141 self.queue_draw()
155 142
156 143
157 class SubTestLabelBox(gtk.EventBox): 144 class SubTestLabelBox(gtk.EventBox):
158 145
159 def __init__(self, test): 146 def __init__(self, test):
160 gtk.EventBox.__init__(self) 147 gtk.EventBox.__init__(self)
161 self.modify_bg(gtk.STATE_NORMAL, _BLACK) 148 self.modify_bg(gtk.STATE_NORMAL, ft.BLACK)
162 label_status = gtk.Label(_UNTESTED) 149 label_status = gtk.Label(ft.UNTESTED)
163 label_status.set_size_request(*_LABEL_STATUS_SIZE) 150 label_status.set_size_request(*_LABEL_STATUS_SIZE)
164 label_status.set_alignment(0, 0.5) 151 label_status.set_alignment(0, 0.5)
165 label_status.modify_font(_LABEL_STATUS_FONT) 152 label_status.modify_font(_LABEL_STATUS_FONT)
166 label_status.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG) 153 label_status.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG)
167 label_en = gtk.Label(test.label_en) 154 label_en = gtk.Label(test.label_en)
168 label_en.set_alignment(1, 0.5) 155 label_en.set_alignment(1, 0.5)
169 label_en.modify_font(_LABEL_EN_FONT) 156 label_en.modify_font(_LABEL_EN_FONT)
170 label_en.modify_fg(gtk.STATE_NORMAL, _LIGHT_GREEN) 157 label_en.modify_fg(gtk.STATE_NORMAL, ft.LIGHT_GREEN)
171 label_zw = gtk.Label(test.label_zw) 158 label_zw = gtk.Label(test.label_zw)
172 label_zw.set_alignment(1, 0.5) 159 label_zw.set_alignment(1, 0.5)
173 label_zw.modify_font(_LABEL_ZW_FONT) 160 label_zw.modify_font(_LABEL_ZW_FONT)
174 label_zw.modify_fg(gtk.STATE_NORMAL, _LIGHT_GREEN) 161 label_zw.modify_fg(gtk.STATE_NORMAL, ft.LIGHT_GREEN)
175 label_sep = gtk.Label(' : ') 162 label_sep = gtk.Label(' : ')
176 label_sep.set_alignment(0.5, 0.5) 163 label_sep.set_alignment(0.5, 0.5)
177 label_sep.modify_font(_LABEL_EN_FONT) 164 label_sep.modify_font(_LABEL_EN_FONT)
178 label_sep.modify_fg(gtk.STATE_NORMAL, _LIGHT_GREEN) 165 label_sep.modify_fg(gtk.STATE_NORMAL, ft.LIGHT_GREEN)
179 hbox = gtk.HBox() 166 hbox = gtk.HBox()
180 hbox.pack_end(label_status, False, False) 167 hbox.pack_end(label_status, False, False)
181 hbox.pack_end(label_sep, False, False) 168 hbox.pack_end(label_sep, False, False)
182 hbox.pack_end(label_zw, False, False) 169 hbox.pack_end(label_zw, False, False)
183 hbox.pack_end(label_en, False, False) 170 hbox.pack_end(label_en, False, False)
184 self.add(hbox) 171 self.add(hbox)
185 self.label_status = label_status 172 self.label_status = label_status
186 173
187 def update(self, status): 174 def update(self, status):
188 if status == _UNTESTED: 175 if status == ft.UNTESTED:
189 return 176 return
190 self.label_status.set_text(status) 177 self.label_status.set_text(status)
191 self.label_status.modify_fg(gtk.STATE_NORMAL, _LABEL_COLORS[status]) 178 self.label_status.modify_fg(gtk.STATE_NORMAL, ft.LABEL_COLORS[status])
192 self.queue_draw() 179 self.queue_draw()
193 180
194 181
195 class StatusMap(): 182 class StatusMap():
196 183
197 def __init__(self, status_file_path, test_list): 184 def __init__(self, status_file_path, test_list):
198 self._test_queue = [t for t in reversed(test_list)] 185 self._test_queue = [t for t in reversed(test_list)]
199 self._as_test_set = set(t for t in test_list if t.automated_seq) 186 self._as_test_set = set(t for t in test_list if t.automated_seq)
200 self._status_dict = {} 187 self._status_dict = {}
201 for test in test_list: 188 for test in test_list:
202 test_index = self.index(test.formal_name, test.tag_prefix) 189 test_index = self.index(test.formal_name, test.tag_prefix)
203 self._status_dict[test_index] = (test, _UNTESTED, 0, None) 190 self._status_dict[test_index] = (test, ft.UNTESTED, 0, None)
204 for subtest in test.automated_seq: 191 for subtest in test.automated_seq:
205 st_index = self.index(subtest.formal_name, subtest.tag_prefix) 192 st_index = self.index(subtest.formal_name, subtest.tag_prefix)
206 self._status_dict[st_index] = (subtest, _UNTESTED, 0, None) 193 self._status_dict[st_index] = (subtest, ft.UNTESTED, 0, None)
207 self._status_file_path = status_file_path 194 self._status_file_path = status_file_path
208 self._status_file_pos = 0 195 self._status_file_pos = 0
209 self.read_new_data() 196 self.read_new_data()
210 gobject.timeout_add(200, self.read_new_data) 197 gobject.timeout_add(200, self.read_new_data)
211 198
212 def index(self, formal_name, tag_prefix): 199 def index(self, formal_name, tag_prefix):
213 return '%s.%s' % (formal_name, tag_prefix) 200 return '%s.%s' % (formal_name, tag_prefix)
214 201
215 def next_untested(self): 202 def next_untested(self):
216 remaining = [t for t in self._test_queue 203 remaining = [t for t in self._test_queue
217 if self.lookup_status(t) == _UNTESTED] 204 if self.lookup_status(t) == ft.UNTESTED]
218 XXX_log('remaining untested = [%s]' % 205 factory.log('remaining untested = [%s]' %
219 ', '.join([self.index(t.formal_name, t.tag_prefix) 206 ', '.join([self.index(t.formal_name, t.tag_prefix)
220 for t in remaining])) 207 for t in remaining]))
221 if not remaining: return None 208 if not remaining: return None
222 return remaining.pop() 209 return remaining.pop()
223 210
224 def read_new_data(self): 211 def read_new_data(self):
225 with open(self._status_file_path) as file: 212 with open(self._status_file_path) as file:
226 file.seek(self._status_file_pos) 213 file.seek(self._status_file_pos)
227 for line in file: 214 for line in file:
228 cols = line.lstrip().split('\t') + [''] 215 cols = line.lstrip().split('\t') + ['']
229 code = cols[0] 216 code = cols[0]
230 test_id = cols[1] 217 test_id = cols[1]
231 if code not in _STATUS_CODE_MAP or test_id == '----': 218 if code not in ft.STATUS_CODE_MAP or test_id == '----':
232 continue 219 continue
233 status = _STATUS_CODE_MAP[code] 220 status = ft.STATUS_CODE_MAP[code]
234 XXX_log('reading code = %s, test_id = %s' % (code, test_id)) 221 factory.log('reading code = %s, test_id = %s' % (code, test_id))
235 formal_name, _, tag = test_id.rpartition('.') 222 formal_name, _, tag = test_id.rpartition('.')
236 tag_prefix, _, count = tag.rpartition('_') 223 tag_prefix, _, count = tag.rpartition('_')
237 self.update(formal_name, tag_prefix, status, int(count)) 224 self.update(formal_name, tag_prefix, status, int(count))
238 self._status_file_pos = file.tell() 225 self._status_file_pos = file.tell()
239 map(self.update_as_test, self._as_test_set) 226 map(self.update_as_test, self._as_test_set)
240 return True 227 return True
241 228
242 def update(self, formal_name, tag_prefix, status, count): 229 def update(self, formal_name, tag_prefix, status, count):
243 test_index = self.index(formal_name, tag_prefix) 230 test_index = self.index(formal_name, tag_prefix)
244 if test_index not in self._status_dict: 231 if test_index not in self._status_dict:
245 XXX_log('ignoring status update (%s) for test %s' % 232 factory.log('ignoring status update (%s) for test %s' %
246 (status, test_index)) 233 (status, test_index))
247 return 234 return
248 test, old_status, old_count, label = self._status_dict[test_index] 235 test, old_status, old_count, label = self._status_dict[test_index]
249 if count < old_count: 236 if count < old_count:
250 XXX_log('ERROR: count regression for %s (%d-%d)' % 237 factory.log('ERROR: count regression for %s (%d-%d)' %
251 (test_index, old_count, count)) 238 (test_index, old_count, count))
252 if status != old_status: 239 if status != old_status:
253 XXX_log('status change for %s : %s/%s -> %s/%s' % 240 factory.log('status change for %s : %s/%s -> %s/%s' %
254 (test_index, old_status, old_count, status, count)) 241 (test_index, old_status, old_count, status, count))
255 if label is not None: 242 if label is not None:
256 label.update(status) 243 label.update(status)
257 self._status_dict[test_index] = (test, status, count, label) 244 self._status_dict[test_index] = (test, status, count, label)
258 245
259 def update_as_test(self, test): 246 def update_as_test(self, test):
260 st_status_set = set(map(self.lookup_status, test.automated_seq)) 247 st_status_set = set(map(self.lookup_status, test.automated_seq))
261 max_count = max(map(self.lookup_count, test.automated_seq)) 248 max_count = max(map(self.lookup_count, test.automated_seq))
262 if len(st_status_set) == 1: 249 if len(st_status_set) == 1:
263 status = st_status_set.pop() 250 status = st_status_set.pop()
264 elif _ACTIVE in st_status_set:
265 status = _ACTIVE
266 else: 251 else:
267 status = _FAILED 252 status = ft.ACTIVE in st_status_set and ft.ACTIVE or ft.FAILED
268 self.update(test.formal_name, test.tag_prefix, status, max_count) 253 self.update(test.formal_name, test.tag_prefix, status, max_count)
269 254
270 def set_label(self, test, label): 255 def set_label(self, test, label):
271 test_index = self.index(test.formal_name, test.tag_prefix) 256 test_index = self.index(test.formal_name, test.tag_prefix)
272 test, status, count, _ = self._status_dict[test_index] 257 test, status, count, _ = self._status_dict[test_index]
273 label.update(status) 258 label.update(status)
274 self._status_dict[test_index] = test, status, count, label 259 self._status_dict[test_index] = test, status, count, label
275 260
276 def lookup_status(self, test): 261 def lookup_status(self, test):
277 test_index = self.index(test.formal_name, test.tag_prefix) 262 test_index = self.index(test.formal_name, test.tag_prefix)
(...skipping 19 matching lines...) Expand all
297 frame = gtk.EventBox() 282 frame = gtk.EventBox()
298 frame.set_size_request(width, -1) 283 frame.set_size_request(width, -1)
299 frame.modify_bg(gtk.STATE_NORMAL, _SEP_COLOR) 284 frame.modify_bg(gtk.STATE_NORMAL, _SEP_COLOR)
300 return frame 285 return frame
301 286
302 287
303 def make_notest_label(): 288 def make_notest_label():
304 label = gtk.Label('no active test') 289 label = gtk.Label('no active test')
305 label.modify_font(_OTHER_LABEL_FONT) 290 label.modify_font(_OTHER_LABEL_FONT)
306 label.set_alignment(0.5, 0.5) 291 label.set_alignment(0.5, 0.5)
307 label.modify_fg(gtk.STATE_NORMAL, _LIGHT_GREEN) 292 label.modify_fg(gtk.STATE_NORMAL, ft.LIGHT_GREEN)
308 box = gtk.EventBox() 293 box = gtk.EventBox()
309 box.modify_bg(gtk.STATE_NORMAL, _BLACK) 294 box.modify_bg(gtk.STATE_NORMAL, ft.BLACK)
310 box.add(label) 295 box.add(label)
311 return box 296 return box
312 297
313 298
314 def make_automated_seq_widget(as_test, status_map): 299 def make_automated_seq_widget(as_test, status_map):
315 vbox = gtk.VBox() 300 vbox = gtk.VBox()
316 vbox.set_spacing(0) 301 vbox.set_spacing(0)
317 map(lambda st: vbox.pack_start(status_map.lookup_label(st), False, False), 302 map(lambda st: vbox.pack_start(status_map.lookup_label(st), False, False),
318 as_test.automated_seq) 303 as_test.automated_seq)
319 return vbox 304 return vbox
320 305
321 306
322 def main(): 307 def main():
323 window = gtk.Window(gtk.WINDOW_TOPLEVEL) 308 window = gtk.Window(gtk.WINDOW_TOPLEVEL)
324 window.connect('destroy', lambda _: gtk.main_quit()) 309 window.connect('destroy', lambda _: gtk.main_quit())
325 window.modify_bg(gtk.STATE_NORMAL, _BLACK) 310 window.modify_bg(gtk.STATE_NORMAL, ft.BLACK)
326 311
327 screen = window.get_screen() 312 screen = window.get_screen()
328 screen_size = (screen.get_width(), screen.get_height()) 313 screen_size = (screen.get_width(), screen.get_height())
329 window.set_size_request(*screen_size) 314 window.set_size_request(*screen_size)
330 315
331 label_trough = gtk.VBox() 316 label_trough = gtk.VBox()
332 label_trough.set_spacing(0) 317 label_trough.set_spacing(0)
333 318
334 rhs_box = gtk.EventBox() 319 rhs_box = gtk.EventBox()
335 rhs_box.modify_bg(gtk.STATE_NORMAL, _LABEL_TROUGH_COLOR) 320 rhs_box.modify_bg(gtk.STATE_NORMAL, _LABEL_TROUGH_COLOR)
336 rhs_box.add(label_trough) 321 rhs_box.add(label_trough)
337 322
338 console_box = gtk.EventBox() 323 console_box = gtk.EventBox()
339 console_box.set_size_request(-1, 180) 324 console_box.set_size_request(-1, 180)
340 console_box.modify_bg(gtk.STATE_NORMAL, _BLACK) 325 console_box.modify_bg(gtk.STATE_NORMAL, ft.BLACK)
341 326
342 notest_label = make_notest_label() 327 notest_label = make_notest_label()
343 328
344 test_widget_box = gtk.Alignment(xalign=0.5, yalign=0.5) 329 test_widget_box = gtk.Alignment(xalign=0.5, yalign=0.5)
345 test_widget_box.set_size_request(-1, -1) 330 test_widget_box.set_size_request(-1, -1)
346 test_widget_box.add(notest_label) 331 test_widget_box.add(notest_label)
347 332
348 lhs_box = gtk.VBox() 333 lhs_box = gtk.VBox()
349 lhs_box.pack_end(console_box, False, False) 334 lhs_box.pack_end(console_box, False, False)
350 lhs_box.pack_start(test_widget_box) 335 lhs_box.pack_start(test_widget_box)
351 lhs_box.pack_start(make_hsep(3), False, False) 336 lhs_box.pack_start(make_hsep(3), False, False)
352 337
353 base_box = gtk.HBox() 338 base_box = gtk.HBox()
354 base_box.pack_end(rhs_box, False, False) 339 base_box.pack_end(rhs_box, False, False)
355 base_box.pack_end(make_vsep(3), False, False) 340 base_box.pack_end(make_vsep(3), False, False)
356 base_box.pack_start(lhs_box) 341 base_box.pack_start(lhs_box)
357 342
358 window.connect('key-release-event', handle_key_release_event) 343 window.connect('key-release-event', handle_key_release_event)
359 window.add_events(gtk.gdk.KEY_RELEASE_MASK) 344 window.add_events(gtk.gdk.KEY_RELEASE_MASK)
360 345
361 # On startup, get general configuration data from the autotest 346 # On startup, get general configuration data from the autotest
362 # control program, specifically the list of tests to run (in 347 # control program, specifically the list of tests to run (in
363 # order) and some filenames. 348 # order) and some filenames.
364 XXX_log('pulling control info') 349 factory.log('pulling control info')
365 test_list = control_recv() 350 test_list = control_recv()
366 status_file_path = control_recv() 351 status_file_path = control_recv()
367 log_file_path = control_recv()
368 352
369 status_map = StatusMap(status_file_path, test_list) 353 status_map = StatusMap(status_file_path, test_list)
370 354
371 for test in test_list: 355 for test in test_list:
372 tlb = TestLabelBox(test) 356 tlb = TestLabelBox(test)
373 status_map.set_label(test, tlb) 357 status_map.set_label(test, tlb)
374 label_trough.pack_start(tlb, False, False) 358 label_trough.pack_start(tlb, False, False)
375 label_trough.pack_start(make_hsep(), False, False) 359 label_trough.pack_start(make_hsep(), False, False)
376 for subtest in test.automated_seq: 360 for subtest in test.automated_seq:
377 stlb = SubTestLabelBox(subtest) 361 stlb = SubTestLabelBox(subtest)
378 status_map.set_label(subtest, stlb) 362 status_map.set_label(subtest, stlb)
379 363
380 window.add(base_box) 364 window.add(base_box)
381 window.show_all() 365 window.show_all()
382 366
383 test_widget_allocation = test_widget_box.get_allocation() 367 test_widget_allocation = test_widget_box.get_allocation()
384 test_widget_size = (test_widget_allocation.width, 368 test_widget_size = (test_widget_allocation.width,
385 test_widget_allocation.height) 369 test_widget_allocation.height)
386 XXX_log('test_widget_size = %s' % repr(test_widget_size)) 370 factory.log('test_widget_size = %s' % repr(test_widget_size))
387 control_send(test_widget_size) 371 control_send(test_widget_size)
388 372
389 trigger_dict = dict((test.trigger, test) for test in test_list) 373 trigger_dict = dict((test.trigger, test) for test in test_list)
390 374
391 gobject.io_add_watch(sys.stdin, gobject.IO_IN, stdin_callback) 375 gobject.io_add_watch(sys.stdin, gobject.IO_IN, stdin_callback)
392 376
393 console = console_proc(console_box.get_allocation(), log_file_path) 377 console = Console(console_box.get_allocation())
394 378
395 XXX_log('finished ui setup') 379 factory.log('finished ui setup')
396 380
397 # Test selection is driven either by triggers or by the 381 # Test selection is driven either by triggers or by the
398 # remaining_tests_queue. If a trigger was seen, explicitly run 382 # remaining_tests_queue. If a trigger was seen, explicitly run
399 # the corresponding test. Otherwise choose the next test from the 383 # the corresponding test. Otherwise choose the next test from the
400 # queue. Tests are removed from the queue as they are run, 384 # queue. Tests are removed from the queue as they are run,
401 # regarless of the outcome. Tests that are interrupted by trigger 385 # regarless of the outcome. Tests that are interrupted by trigger
402 # are treated as having failed. 386 # are treated as having failed.
403 # 387 #
404 # Iterations in the main loop here are driven by data availability 388 # Iterations in the main loop here are driven by data availability
405 # on stdin, which is used to communicate with the autotest control 389 # on stdin, which is used to communicate with the autotest control
406 # program. On each step through the loop, a trigger is received 390 # program. On each step through the loop, a trigger is received
407 # (possibly None) to indicate how the next test should be selected. 391 # (possibly None) to indicate how the next test should be selected.
408 392
409 while True: 393 while True:
410 command, arg = control_recv() 394 command, arg = control_recv()
411 XXX_log('ui received command %s(%s)' % (command, arg)) 395 factory.log('ui received command %s(%s)' % (command, arg))
412 if command == 'switch_to': 396 if command == 'switch_to':
413 next_test = trigger_dict.get(arg, None) 397 next_test = trigger_dict.get(arg, None)
414 elif command == 'next_test': 398 elif command == 'next_test':
415 next_test = status_map.next_untested() 399 next_test = status_map.next_untested()
416 else: 400 else:
417 XXX_log('ui command unknown, exiting...') 401 factory.log('ui command unknown, exiting...')
418 break 402 break
419 control_send_target_test_update( 403 control_send_target_test_update(
420 next_test, status_map.lookup_count(next_test) + 1) 404 next_test, status_map.lookup_count(next_test) + 1)
421 if next_test.automated_seq: 405 if next_test.automated_seq:
422 XXX_log('ui starting automated_seq') 406 factory.log('ui starting automated_seq')
423 test_widget_box.remove(notest_label) 407 test_widget_box.remove(notest_label)
424 as_widget = make_automated_seq_widget(next_test, status_map) 408 as_widget = make_automated_seq_widget(next_test, status_map)
425 test_widget_box.add(as_widget) 409 test_widget_box.add(as_widget)
426 window.show_all() 410 window.show_all()
427 gtk.main() 411 gtk.main()
428 command = control_recv() 412 command = control_recv()
429 XXX_log('ui automated_seq cmd (%s)' % command) 413 factory.log('ui automated_seq cmd (%s)' % command)
430 test_widget_box.remove(as_widget) 414 test_widget_box.remove(as_widget)
431 test_widget_box.add(notest_label) 415 test_widget_box.add(notest_label)
432 window.show_all() 416 window.show_all()
433 XXX_log('ui exiting automated_seq') 417 factory.log('ui exiting automated_seq')
434 else: 418 else:
435 gtk.main() 419 gtk.main()
436 420
437 # Tell the control process we are done. 421 # Tell the control process we are done.
438 control_send((None, 0)) 422 control_send((None, 0))
439 423
440 XXX_log('exiting ui') 424 factory.log('exiting ui')
441 425
442 if __name__ == '__main__': 426 if __name__ == '__main__':
443
444 # In global scope, get the test_data class description from the
445 # control program -- this allows a convenient single point of
446 # definition for this class.
447 test_data_class_def = control_recv()
448 exec(test_data_class_def)
449
450 main() 427 main()
OLDNEW
« no previous file with comments | « client/bin/factory.py ('k') | client/bin/factory_ui_lib.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698