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

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

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/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_Camera', 76 factory.TestData(
102 trigger='c'), 77 label_en='system stress',
103 test_data( 78 label_zw='壓力測試',
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(
104 label_en='keyboard', 86 label_en='keyboard',
105 label_zw='鍵盤', 87 label_zw='鍵盤',
106 formal_name='factory_Keyboard', 88 formal_name='factory_Keyboard',
107 trigger='k', 89 trigger='k',
108 dargs={'layout':'en_us'}), 90 dargs={'layout':'en_us'}),
109 test_data( 91 factory.TestData(
110 label_en='touchpad', 92 label_en='touchpad',
111 label_zw='觸控板', 93 label_zw='觸控板',
112 formal_name='factory_Touchpad', 94 formal_name='factory_Touchpad',
113 trigger='t'), 95 trigger='t'),
114 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_Camera',
111 trigger='c'),
112 factory.TestData(
113 label_en='audio',
114 label_zw='聲音',
115 formal_name='factory_Dummy',
116 trigger='a',
117 dargs={'msg':'audio test, one day...'}),
118 factory.TestData(
119 label_en='usb',
120 formal_name='factory_ExternalStorage',
121 trigger='u'),
122 factory.TestData(
123 label_en='sd',
124 formal_name='factory_ExternalStorage',
125 trigger='d'),
126 factory.TestData(
127 label_en='bluetooth',
128 label_zw='藍牙',
129 formal_name='factory_Dummy',
130 trigger='o',
131 dargs={'msg':'bluetooth test, one day...'}),
132 factory.TestData(
133 label_en='3g',
134 label_zw='第三代',
135 formal_name='factory_Dummy',
136 trigger='g',
137 dargs={'msg':'3g test, one day...'}),
138 factory.TestData(
139 label_en='wifi',
140 label_zw='無線上網',
141 formal_name='factory_Dummy',
142 trigger='w',
143 dargs={'msg':'wifi test, one day...'}),
144 factory.TestData(
115 label_en='devrec', 145 label_en='devrec',
146 label_zw='特殊模式',
116 formal_name='factory_DeveloperRecovery', 147 formal_name='factory_DeveloperRecovery',
117 trigger='d', 148 trigger='b',
118 dargs={'layout':'devrec'}), 149 dargs={'layout':'devrec'}),
119 test_data( 150 factory.TestData(
120 label_en='run-in', 151 label_en='final check',
121 formal_name='step_runin', 152 label_zw='最後檢查',
122 automated_seq=[
123 test_data(
124 label_en='component validation',
125 formal_name='hardware_Components',
126 dargs={'approved_db':'qualified_components'}),
127 test_data(
128 label_en='gpio switch check',
129 formal_name='hardware_GPIOSwitches'),
130 test_data(
131 label_en='system stress',
132 formal_name='hardware_SAT'),
133 test_data(
134 label_en='reboot (%s times)' % _REBOOT_SEQ_ITERATIONS,
135 formal_name='factory_RebootStub')],
136 trigger='r'),
137 test_data(
138 label_en='end',
139 formal_name='factory_Dummy', 153 formal_name='factory_Dummy',
140 trigger='e', 154 trigger='f',
141 dargs={'msg':'end of testing...\n(chinese)...'}), 155 dargs={'msg':'google required checks...'}),
156 factory.TestData(
157 label_en='wipe',
158 label_zw='擦拭',
159 formal_name='factory_Dummy',
160 trigger='x',
161 dargs={'msg':('hit TAB+RETURN to finish testing and wipe test image!' +
162 '...\n(chinese)...')}),
142 ] 163 ]
143 164
144 for test in test_list: 165 for test in test_list:
145 test.tag_prefix = test.trigger 166 test.tag_prefix = test.trigger
146 for subtest in test.automated_seq: 167 for subtest in test.automated_seq:
147 subtest.tag_prefix = test.formal_name 168 subtest.tag_prefix = test.formal_name
148 169
149 def test_map_index(formal_name, tag_prefix): 170 test_map = factory.make_test_map(test_list)
150 return formal_name + '.' + tag_prefix 171 trigger_set = factory.make_trigger_set(test_list)
151
152 test_map = dict((test_map_index(test.formal_name, test.tag_prefix), test)
153 for test in test_list)
154
155 trigger_set = set(test.trigger for test in test_list)
156
157
158 class factory_ui:
159 '''Support communication with the factory_ui process. To simplify
160 surrounding code, this communication is an exchange of well formed
161 python expressions. Basically send wraps its arguments in a call
162 to repr() and recv calls eval() to re-generate the python data.'''
163
164 def __init__(self, factory_ui_path):
165 self._proc = subprocess.Popen(factory_ui_path,
166 stdin=subprocess.PIPE,
167 stdout=subprocess.PIPE)
168
169 def __del__(self):
170 XXX_log('control deleting factory_ui subprocess')
171 self._proc.terminate()
172 time.sleep(1)
173 if self._proc.poll() is None:
174 self._proc.kill()
175
176 def send(self, x=None):
177 print >> self._proc.stdin, repr(x)
178 self._proc.stdin.flush()
179
180 def send_cmd_next_test(self):
181 self.send(('next_test', None))
182
183 def send_cmd_switch_to(self, trigger):
184 self.send(('switch_to', trigger))
185
186 def recv(self):
187 return eval(self._proc.stdout.readline().rstrip())
188
189 def recv_target_test_update(self):
190 update = self.recv()
191 XXX_log('control recv target test %s' % repr(update))
192 formal_name, tag_prefix, count = update
193 test = test_map.get(test_map_index(formal_name, tag_prefix), None)
194 return (test, count)
195 172
196 173
197 def step_reboot_seq(i, tag): 174 def step_reboot_seq(i, tag):
198 if i < _REBOOT_SEQ_ITERATIONS: 175 if i < _REBOOT_SEQ_ITERATIONS:
199 job.next_step_prepend([step_reboot_seq, i + 1, tag]) 176 job.next_step_prepend([step_reboot_seq, i + 1, tag])
200 XXX_log('rebooting (iteration %d)' % i) 177 factory.log('rebooting (iteration %d)' % i)
201 time.sleep(5) 178 time.sleep(5)
202 job.reboot() 179 job.reboot()
203 else: 180 else:
204 job.run_test('factory_RebootStub', tag=tag) 181 job.run_test('factory_RebootStub', tag=tag)
205 step_init() 182 step_init()
206 183
207 184
208 def step_runin(ui, tag): 185 def step_runin(ui, tag):
209 job.run_test('hardware_Components', 186 job.run_test('hardware_Components',
210 approved_db='qualified_components', 187 approved_db='qualified_components',
(...skipping 12 matching lines...) Expand all
223 out-of-order test execution based on keyboard shortcuts. 200 out-of-order test execution based on keyboard shortcuts.
224 201
225 For each test, a trigger (possibly None) is communicated to the 202 For each test, a trigger (possibly None) is communicated to the
226 UI, which then replies with the test name and a count number that 203 UI, which then replies with the test name and a count number that
227 becomes the autotest tag to allow repeated test execution while 204 becomes the autotest tag to allow repeated test execution while
228 preserving logs. 205 preserving logs.
229 206
230 When the tests themselves run, they are expected to look for 207 When the tests themselves run, they are expected to look for
231 (using the factory_test library) keyboard events that match test 208 (using the factory_test library) keyboard events that match test
232 switching triggers. When a trigger happens, it should be written 209 switching triggers. When a trigger happens, it should be written
233 to the _RESULT_FILE_PATH, which will be read after the test 210 to the factory.RESULT_FILE_PATH, which will be read after the test
234 completed and the result comminicated onwards to the UI.''' 211 completed and the result comminicated onwards to the UI.'''
235 212
236 job.next_step([step_init]) 213 job.next_step([step_init])
237 214
238 status_file_path = job.autodir + '/results/default/status' 215 ui = factory.UiClient(_FACTORY_UI_PATH)
239 factory_ui_path = job.autodir + '/deps/factory/ui'
240 216
241 ui = factory_ui(factory_ui_path)
242
243 ui.send(test_data_class_def)
244 ui.send(test_list) 217 ui.send(test_list)
245 ui.send(status_file_path) 218 ui.send(_STATUS_FILE_PATH)
246 ui.send(_FACTORY_LOG_PATH)
247 219
248 test_widget_size = ui.recv() 220 test_widget_size = ui.recv()
249 XXX_log('received test_widget_size = %s' % repr(test_widget_size)) 221 factory.log('received test_widget_size = %s' % repr(test_widget_size))
250 222
251 ui.send_cmd_next_test() 223 ui.send_cmd_next_test()
252 test, test_count = ui.recv_target_test_update() 224 test, test_count = ui.recv_target_test_update(test_map)
253 225
254 while test is not None: 226 while test is not None:
255 if test.automated_seq: 227 if test.automated_seq:
256 tag = '%s_%s' % (test.formal_name, test_count) 228 tag = '%s_%s' % (test.formal_name, test_count)
257 exec('%s(ui, "%s")' % (test.formal_name, tag)) 229 exec('%s(ui, "%s")' % (test.formal_name, tag))
258 result = None 230 result = None
259 else: 231 else:
260 dargs = test.dargs 232 dargs = test.dargs
261 dargs.update({ 233 dargs.update({
262 'tag': '%s_%s' % (test.tag_prefix, test_count), 234 'tag': '%s_%s' % (test.tag_prefix, test_count),
263 'test_tag_prefix': test.tag_prefix, 235 'test_tag_prefix': test.tag_prefix,
264 'test_count': test_count, 236 'test_count': test_count,
265 'test_widget_size': test_widget_size, 237 'test_widget_size': test_widget_size,
266 'trigger_set': trigger_set, 238 'trigger_set': trigger_set,
267 'result_file_path': _RESULT_FILE_PATH}) 239 'result_file_path': factory.RESULT_FILE_PATH})
268 with open(_RESULT_FILE_PATH, 'w') as file: 240 with open(factory.RESULT_FILE_PATH, 'w') as file:
269 file.write('None\n') 241 file.write('None\n')
270 job.run_test(test.formal_name, **dargs) 242 job.run_test(test.formal_name, **dargs)
271 with open(_RESULT_FILE_PATH, 'r') as file: 243 with open(factory.RESULT_FILE_PATH, 'r') as file:
272 result = eval(file.readline()) 244 result = eval(file.readline())
273 245
274 if result is not None: 246 if result is not None:
275 ui.send_cmd_switch_to(result) 247 ui.send_cmd_switch_to(result)
276 else: 248 else:
277 ui.send_cmd_next_test() 249 ui.send_cmd_next_test()
278 250
279 test, test_count = ui.recv_target_test_update() 251 test, test_count = ui.recv_target_test_update(test_map)
280 252
281 XXX_log('factory testing completed') 253 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