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

Side by Side Diff: client/site_tests/suite_Factory/control

Issue 2805052: Relocate library files for wider access and re-use; also associated cleanup. (Closed) Base URL: ssh://gitrw.chromium.org/autotest.git
Patch Set: address nicks comment 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/site_tests/factory_Touchpad/factory_Touchpad.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
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 AUTHOR = "Chrome OS Team" 7 AUTHOR = "Chrome OS Team"
8 NAME = "Factory" 8 NAME = "Factory"
9 TIME = "LONG" 9 TIME = "LONG"
10 TEST_CATEGORY = "Functional" 10 TEST_CATEGORY = "Functional"
11 TEST_CLASS = "suite" 11 TEST_CLASS = "suite"
12 TEST_TYPE = "client" 12 TEST_TYPE = "client"
13 13
14 DOC = """ 14 DOC = """
15 This suite executed all of the factory tests, and incorporates an 15 This suite executed all of the factory tests, and incorporates an
16 X-windows GTK-based UI to highlight testing results and to allow 16 X-windows GTK-based UI to highlight testing results and to allow
17 factory operators to switch between tests, and to re-run tests, all 17 factory operators to switch between tests, and to re-run tests, all
18 on-demand via keyboard shortcuts. 18 on-demand via keyboard shortcuts.
19 19
20 The UI is implemented as a seperate process (see _FACTORY_UI_PATH), 20 The UI is implemented as a seperate process (see _FACTORY_UI_PATH),
21 which means that interprocess communication is needed between this 21 which means that interprocess communication is needed between this
22 control, the UI, and the tests (which are forked children of this 22 control, the UI, and the tests (which are forked children of this
23 control process). """ 23 control process). """
24 24
25 25
26 import imp
26 import subprocess 27 import subprocess
27 import sys 28 import sys
28 import time 29 import time
29 30
31 imp.load_source('common', job.autodir + '/bin/common.py')
32 from autotest_lib.client.bin import factory
30 33
31 _FACTORY_LOG_PATH = '/var/log/factory.log' 34
32 _RESULT_FILE_PATH = '/var/run/factory_test_result' 35 _STATUS_FILE_PATH = job.autodir + '/results/default/status'
36 _FACTORY_UI_PATH = job.autodir + '/bin/factory_ui'
37
33 38
34 _REBOOT_SEQ_ITERATIONS = 2 39 _REBOOT_SEQ_ITERATIONS = 2
35 40
36 41
37 def XXX_log(s):
38 print >> sys.stderr, 'FACTORY: ' + s
39
40
41 # Hack to work around autotest's obsession with GRUB. 42 # Hack to work around autotest's obsession with GRUB.
42 job.bootloader.set_default = lambda x: None 43 job.bootloader.set_default = lambda x: None
43 job.bootloader.boot_once = lambda x: None 44 job.bootloader.boot_once = lambda x: None
44 45
45 46
46 # This is the definition of the test_data class, which holds
47 # factory-specific information on the tests to be run. Specifically,
48 # the order of items in the list reflect the order they are to be run
49 # on the line. The label and trigger fields contain the description
50 # strings to be shown in the test control list of the UI. The trigger
51 # field specifies the keyboard shortcut to allow on-demain
52 # out-of-order test activation. The dargs field allows test specific
53 # extra arguments. Note: this datastructure is defined as a string
54 # and exec()ed to allow it to be defined once here, but to be also
55 # used by the factory_ui process.
56
57 test_data_class_def = '''
58 class test_data:
59
60 def __init__(self, label_en='', label_zw='', formal_name=None,
61 tag_prefix=None, trigger=None, automated_seq=[], dargs={}):
62 self.__dict__.update(vars())
63
64 def __repr__(self):
65 d = ['%s=%s' % (l,repr(v))
66 for l,v in self.__dict__.items()
67 if l != 'self']
68 c = ('%s' % self.__class__).rpartition('.')[2]
69 return '%s(%s)' % (c, ','.join(d))
70 '''
71 exec(test_data_class_def)
72
73
74 test_list = [ 47 test_list = [
75 test_data( 48 factory.TestData(
76 label_en='start', 49 label_en='start',
50 label_zw='開始',
77 formal_name='factory_Dummy', 51 formal_name='factory_Dummy',
78 trigger='a', 52 trigger='e',
79 dargs={'quit_key':ord(' '), 53 dargs={'quit_key':ord(' '),
80 'msg':'Hit SPACE to start testing...\n按 "空白鍵" 開始測試...'}), 54 'msg':'Hit SPACE to start testing...\n按 "空白鍵" 開始測試...'}),
81 test_data( 55 factory.TestData(
82 label_en='sync', 56 label_en='sync',
57 label_zw='同步',
83 formal_name='factory_ScriptWrapper', 58 formal_name='factory_ScriptWrapper',
84 trigger='s', 59 trigger='s',
85 dargs={'cmdline':'/usr/local/autotest/exscr'}), 60 dargs={'cmdline': job.autodir +
86 test_data( 61 '/site_tests/factory_ScriptWrapper/dummy.sh'}),
87 label_en='leds', 62 factory.TestData(
88 formal_name='factory_Dummy', 63 label_en='run-in',
89 trigger='l', 64 label_zw='燒機測試',
90 dargs={'msg':'LEDs test, one day...'}), 65 formal_name='step_runin',
91 test_data( 66 automated_seq=[
92 label_en='usb', 67 factory.TestData(
93 formal_name='factory_ExternalStorage', 68 label_en='component validation',
94 trigger='u'), 69 label_zw='元件驗證',
95 test_data( 70 formal_name='hardware_Components',
96 label_en='display', 71 dargs={'approved_db':'qualified_components'}),
97 formal_name='factory_Display', 72 factory.TestData(
98 trigger='m'), 73 label_en='gpio switch check',
99 test_data( 74 label_zw='檢查 gpio 開關',
100 label_en='camera', 75 formal_name='hardware_GPIOSwitches'),
101 formal_name='factory_Dummy', 76 factory.TestData(
102 trigger='c', 77 label_en='system stress',
103 dargs={'msg':'camera test, one day...'}), 78 label_zw='壓力測試',
104 test_data( 79 formal_name='hardware_SAT'),
80 factory.TestData(
81 label_en='reboot (%s times)' % _REBOOT_SEQ_ITERATIONS,
82 label_zw='重新開機 (%s 次)' % _REBOOT_SEQ_ITERATIONS,
83 formal_name='factory_RebootStub')],
84 trigger='r'),
85 factory.TestData(
105 label_en='keyboard', 86 label_en='keyboard',
106 label_zw='鍵盤', 87 label_zw='鍵盤',
107 formal_name='factory_Keyboard', 88 formal_name='factory_Keyboard',
108 trigger='k', 89 trigger='k',
109 dargs={'layout':'en_us'}), 90 dargs={'layout':'en_us'}),
110 test_data( 91 factory.TestData(
111 label_en='touchpad', 92 label_en='touchpad',
112 label_zw='觸控板', 93 label_zw='觸控板',
113 formal_name='factory_Touchpad', 94 formal_name='factory_Touchpad',
114 trigger='t'), 95 trigger='t'),
115 test_data( 96 factory.TestData(
97 label_en='leds',
98 label_zw='機身側燈',
99 formal_name='factory_Dummy',
100 trigger='l',
101 dargs={'msg':'LEDs test, one day...'}),
102 factory.TestData(
103 label_en='display',
104 label_zw='顯示',
105 formal_name='factory_Display',
106 trigger='m'),
107 factory.TestData(
108 label_en='camera',
109 label_zw='相機',
110 formal_name='factory_Dummy',
111 trigger='c',
112 dargs={'msg':'camera test, one day...'}),
113 factory.TestData(
114 label_en='audio',
115 label_zw='聲音',
116 formal_name='factory_Dummy',
117 trigger='a',
118 dargs={'msg':'audio test, one day...'}),
119 factory.TestData(
120 label_en='usb',
121 formal_name='factory_ExternalStorage',
122 trigger='u'),
123 factory.TestData(
124 label_en='sd',
125 formal_name='factory_ExternalStorage',
126 trigger='d'),
127 factory.TestData(
128 label_en='bluetooth',
129 label_zw='藍牙',
130 formal_name='factory_Dummy',
131 trigger='o',
132 dargs={'msg':'bluetooth test, one day...'}),
133 factory.TestData(
134 label_en='3g',
135 label_zw='第三代',
136 formal_name='factory_Dummy',
137 trigger='g',
138 dargs={'msg':'3g test, one day...'}),
139 factory.TestData(
140 label_en='wifi',
141 label_zw='無線上網',
142 formal_name='factory_Dummy',
143 trigger='w',
144 dargs={'msg':'wifi test, one day...'}),
145 factory.TestData(
116 label_en='devrec', 146 label_en='devrec',
147 label_zw='特殊模式',
117 formal_name='factory_DeveloperRecovery', 148 formal_name='factory_DeveloperRecovery',
118 trigger='d', 149 trigger='b',
119 dargs={'layout':'devrec'}), 150 dargs={'layout':'devrec'}),
120 test_data( 151 factory.TestData(
121 label_en='run-in', 152 label_en='final check',
122 formal_name='step_runin', 153 label_zw='最後檢查',
123 automated_seq=[
124 test_data(
125 label_en='component validation',
126 formal_name='hardware_Components',
127 dargs={'approved_db':'qualified_components'}),
128 test_data(
129 label_en='gpio switch check',
130 formal_name='hardware_GPIOSwitches'),
131 test_data(
132 label_en='system stress',
133 formal_name='hardware_SAT'),
134 test_data(
135 label_en='reboot (%s times)' % _REBOOT_SEQ_ITERATIONS,
136 formal_name='factory_RebootStub')],
137 trigger='r'),
138 test_data(
139 label_en='end',
140 formal_name='factory_Dummy', 154 formal_name='factory_Dummy',
141 trigger='e', 155 trigger='f',
142 dargs={'msg':'end of testing...\n(chinese)...'}), 156 dargs={'msg':'google required checks...'}),
157 factory.TestData(
158 label_en='wipe',
159 label_zw='擦拭',
160 formal_name='factory_Dummy',
161 trigger='x',
162 dargs={'msg':('hit TAB+RETURN to finish testing and wipe test image!' +
163 '...\n(chinese)...')}),
143 ] 164 ]
144 165
145 for test in test_list: 166 for test in test_list:
146 test.tag_prefix = test.trigger 167 test.tag_prefix = test.trigger
147 for subtest in test.automated_seq: 168 for subtest in test.automated_seq:
148 subtest.tag_prefix = test.formal_name 169 subtest.tag_prefix = test.formal_name
149 170
150 def test_map_index(formal_name, tag_prefix): 171 test_map = factory.make_test_map(test_list)
151 return formal_name + '.' + tag_prefix 172 trigger_set = factory.make_trigger_set(test_list)
152
153 test_map = dict((test_map_index(test.formal_name, test.tag_prefix), test)
154 for test in test_list)
155
156 trigger_set = set(test.trigger for test in test_list)
157
158
159 class factory_ui:
160 '''Support communication with the factory_ui process. To simplify
161 surrounding code, this communication is an exchange of well formed
162 python expressions. Basically send wraps its arguments in a call
163 to repr() and recv calls eval() to re-generate the python data.'''
164
165 def __init__(self, factory_ui_path):
166 self._proc = subprocess.Popen(factory_ui_path,
167 stdin=subprocess.PIPE,
168 stdout=subprocess.PIPE)
169
170 def __del__(self):
171 XXX_log('control deleting factory_ui subprocess')
172 self._proc.terminate()
173 time.sleep(1)
174 if self._proc.poll() is None:
175 self._proc.kill()
176
177 def send(self, x=None):
178 print >> self._proc.stdin, repr(x)
179 self._proc.stdin.flush()
180
181 def send_cmd_next_test(self):
182 self.send(('next_test', None))
183
184 def send_cmd_switch_to(self, trigger):
185 self.send(('switch_to', trigger))
186
187 def recv(self):
188 return eval(self._proc.stdout.readline().rstrip())
189
190 def recv_target_test_update(self):
191 update = self.recv()
192 XXX_log('control recv target test %s' % repr(update))
193 formal_name, tag_prefix, count = update
194 test = test_map.get(test_map_index(formal_name, tag_prefix), None)
195 return (test, count)
196 173
197 174
198 def step_reboot_seq(i, tag): 175 def step_reboot_seq(i, tag):
199 if i < _REBOOT_SEQ_ITERATIONS: 176 if i < _REBOOT_SEQ_ITERATIONS:
200 job.next_step_prepend([step_reboot_seq, i + 1, tag]) 177 job.next_step_prepend([step_reboot_seq, i + 1, tag])
201 XXX_log('rebooting (iteration %d)' % i) 178 factory.log('rebooting (iteration %d)' % i)
202 time.sleep(5) 179 time.sleep(5)
203 job.reboot() 180 job.reboot()
204 else: 181 else:
205 job.run_test('factory_RebootStub', tag=tag) 182 job.run_test('factory_RebootStub', tag=tag)
206 step_init() 183 step_init()
207 184
208 185
209 def step_runin(ui, tag): 186 def step_runin(ui, tag):
210 job.run_test('hardware_Components', 187 job.run_test('hardware_Components',
211 approved_db='qualified_components', 188 approved_db='qualified_components',
(...skipping 12 matching lines...) Expand all
224 out-of-order test execution based on keyboard shortcuts. 201 out-of-order test execution based on keyboard shortcuts.
225 202
226 For each test, a trigger (possibly None) is communicated to the 203 For each test, a trigger (possibly None) is communicated to the
227 UI, which then replies with the test name and a count number that 204 UI, which then replies with the test name and a count number that
228 becomes the autotest tag to allow repeated test execution while 205 becomes the autotest tag to allow repeated test execution while
229 preserving logs. 206 preserving logs.
230 207
231 When the tests themselves run, they are expected to look for 208 When the tests themselves run, they are expected to look for
232 (using the factory_test library) keyboard events that match test 209 (using the factory_test library) keyboard events that match test
233 switching triggers. When a trigger happens, it should be written 210 switching triggers. When a trigger happens, it should be written
234 to the _RESULT_FILE_PATH, which will be read after the test 211 to the factory.RESULT_FILE_PATH, which will be read after the test
235 completed and the result comminicated onwards to the UI.''' 212 completed and the result comminicated onwards to the UI.'''
236 213
237 job.next_step([step_init]) 214 job.next_step([step_init])
238 215
239 status_file_path = job.autodir + '/results/default/status' 216 ui = factory.UiClient(_FACTORY_UI_PATH)
240 factory_ui_path = job.autodir + '/deps/factory/ui'
241 217
242 ui = factory_ui(factory_ui_path)
243
244 ui.send(test_data_class_def)
245 ui.send(test_list) 218 ui.send(test_list)
246 ui.send(status_file_path) 219 ui.send(_STATUS_FILE_PATH)
247 ui.send(_FACTORY_LOG_PATH)
248 220
249 test_widget_size = ui.recv() 221 test_widget_size = ui.recv()
250 XXX_log('received test_widget_size = %s' % repr(test_widget_size)) 222 factory.log('received test_widget_size = %s' % repr(test_widget_size))
251 223
252 ui.send_cmd_next_test() 224 ui.send_cmd_next_test()
253 test, test_count = ui.recv_target_test_update() 225 test, test_count = ui.recv_target_test_update(test_map)
254 226
255 while test is not None: 227 while test is not None:
256 if test.automated_seq: 228 if test.automated_seq:
257 tag = '%s_%s' % (test.formal_name, test_count) 229 tag = '%s_%s' % (test.formal_name, test_count)
258 exec('%s(ui, "%s")' % (test.formal_name, tag)) 230 exec('%s(ui, "%s")' % (test.formal_name, tag))
259 result = None 231 result = None
260 else: 232 else:
261 dargs = test.dargs 233 dargs = test.dargs
262 dargs.update({ 234 dargs.update({
263 'tag': '%s_%s' % (test.tag_prefix, test_count), 235 'tag': '%s_%s' % (test.tag_prefix, test_count),
264 'test_tag_prefix': test.tag_prefix, 236 'test_tag_prefix': test.tag_prefix,
265 'test_count': test_count, 237 'test_count': test_count,
266 'test_widget_size': test_widget_size, 238 'test_widget_size': test_widget_size,
267 'trigger_set': trigger_set, 239 'trigger_set': trigger_set,
268 'result_file_path': _RESULT_FILE_PATH}) 240 'result_file_path': factory.RESULT_FILE_PATH})
269 with open(_RESULT_FILE_PATH, 'w') as file: 241 with open(factory.RESULT_FILE_PATH, 'w') as file:
270 file.write('None\n') 242 file.write('None\n')
271 job.run_test(test.formal_name, **dargs) 243 job.run_test(test.formal_name, **dargs)
272 with open(_RESULT_FILE_PATH, 'r') as file: 244 with open(factory.RESULT_FILE_PATH, 'r') as file:
273 result = eval(file.readline()) 245 result = eval(file.readline())
274 246
275 if result is not None: 247 if result is not None:
276 ui.send_cmd_switch_to(result) 248 ui.send_cmd_switch_to(result)
277 else: 249 else:
278 ui.send_cmd_next_test() 250 ui.send_cmd_next_test()
279 251
280 test, test_count = ui.recv_target_test_update() 252 test, test_count = ui.recv_target_test_update(test_map)
281 253
282 XXX_log('factory testing completed') 254 factory.log('factory testing completed')
OLDNEW
« no previous file with comments | « client/site_tests/factory_Touchpad/factory_Touchpad.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698