blob: 7bff3d6d2e999cd0ada156a16405c6ffe41cfb0d [file] [log] [blame]
Gaurav Shaha7fb8962011-08-16 15:06:32 -07001# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Daniel Erat3e3f7f42010-03-29 17:19:14 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Elly Jones2f0ebba2011-10-27 13:43:20 -04005import logging, os, platform, re, signal, tempfile, time, uuid
Daniel Erat3e3f7f42010-03-29 17:19:14 -07006from autotest_lib.client.common_lib import error
Vadim Bendeburye7970922011-04-07 17:07:37 -07007from autotest_lib.client.common_lib import utils
Daniel Erat3e3f7f42010-03-29 17:19:14 -07008
rgindaf25f73f2010-04-07 14:55:25 -07009class TimeoutError(error.TestError):
10 """Error raised when we time out when waiting on a condition."""
David Jamesd51ac9c2011-09-10 00:45:24 -070011 pass
rgindaf25f73f2010-04-07 14:55:25 -070012
13
Vadim Bendeburye7970922011-04-07 17:07:37 -070014class Crossystem(object):
15 """A wrapper for the crossystem utility."""
16
17 def __init__(self, client):
18 self.cros_system_data = {}
19 self._client = client
20
21 def init(self):
22 self.cros_system_data = {}
23 (_, fname) = tempfile.mkstemp()
24 f = open(fname, 'w')
25 self._client.run('crossystem', stdout_tee=f)
26 f.close()
27 text = utils.read_file(fname)
28 for line in text.splitlines():
29 assignment_string = line.split('#')[0]
30 if not assignment_string.count('='):
31 continue
32 (name, value) = assignment_string.split('=', 1)
33 self.cros_system_data[name.strip()] = value.strip()
34 os.remove(fname)
35
36 def __getattr__(self, name):
37 """
38 Retrieve a crosssystem attribute.
39
40 The call crossystemobject.name() will return the crossystem reported
41 string.
42 """
43 return lambda : self.cros_system_data[name]
44
45
David Jamesd51ac9c2011-09-10 00:45:24 -070046def nuke_process_by_name(name, with_prejudice=False):
47 try:
48 pid = int(utils.system_output('pgrep -o ^%s$' % name).split()[0])
49 except Exception as e:
50 logging.error(e)
51 return
52 if with_prejudice:
53 utils.nuke_pid(pid, [signal.SIGKILL])
54 else:
55 utils.nuke_pid(pid)
56
57
Daniel Erat3e3f7f42010-03-29 17:19:14 -070058def poll_for_condition(
rgindaf25f73f2010-04-07 14:55:25 -070059 condition, exception=None, timeout=10, sleep_interval=0.1, desc=None):
Daniel Erat3e3f7f42010-03-29 17:19:14 -070060 """Poll until a condition becomes true.
61
Jon Salz4f646a32011-11-30 14:42:51 +080062 Arguments:
63 condition: function taking no args and returning bool
64 exception: exception to throw if condition doesn't become true
65 timeout: maximum number of seconds to wait
66 sleep_interval: time to sleep between polls
67 desc: description of default TimeoutError used if 'exception' is None
68
69 Returns:
70 The true value that caused the poll loop to terminate.
Daniel Erat3e3f7f42010-03-29 17:19:14 -070071
72 Raises:
rgindaf25f73f2010-04-07 14:55:25 -070073 'exception' arg if supplied; site_utils.TimeoutError otherwise
Daniel Erat3e3f7f42010-03-29 17:19:14 -070074 """
75 start_time = time.time()
76 while True:
Jon Salz4f646a32011-11-30 14:42:51 +080077 value = condition()
78 if value:
79 return value
Daniel Erat3e3f7f42010-03-29 17:19:14 -070080 if time.time() + sleep_interval - start_time > timeout:
rgindaf25f73f2010-04-07 14:55:25 -070081 if exception:
Gaurav Shaha7fb8962011-08-16 15:06:32 -070082 logging.error(exception)
rgindaf25f73f2010-04-07 14:55:25 -070083 raise exception
84
85 if desc:
86 desc = 'Timed out waiting for condition: %s' % desc
87 else:
88 desc = 'Timed out waiting for unnamed condition'
Gaurav Shaha7fb8962011-08-16 15:06:32 -070089 logging.error(desc)
Mitsuru Oshima5d3e4542010-08-18 13:46:06 -070090 raise TimeoutError, desc
rgindaf25f73f2010-04-07 14:55:25 -070091
Daniel Erat3e3f7f42010-03-29 17:19:14 -070092 time.sleep(sleep_interval)
Thieu Le1904d002010-11-30 17:10:24 -080093
94
95def save_vm_state(checkpoint):
96 """Saves the current state of the virtual machine.
97
98 This function is a NOOP if the test is not running under a virtual machine
99 with the USB serial port redirected.
100
101 Arguments:
102 checkpoint - Name used to identify this state
103
104 Returns:
105 None
106 """
107 # The QEMU monitor has been redirected to the guest serial port located at
108 # /dev/ttyUSB0. To save the state of the VM, we just send the 'savevm'
109 # command to the serial port.
110 proc = platform.processor()
111 if 'QEMU' in proc and os.path.exists('/dev/ttyUSB0'):
112 logging.info('Saving VM state "%s"' % checkpoint)
113 serial = open('/dev/ttyUSB0', 'w')
114 serial.write("savevm %s\r\n" % checkpoint)
115 logging.info('Done saving VM state "%s"' % checkpoint)
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -0800116
117
118def check_raw_dmesg(dmesg, message_level, whitelist):
119 """Checks dmesg for unexpected warnings.
120
121 This function parses dmesg for message with message_level <= message_level
122 which do not appear in the whitelist.
123
124 Arguments:
125 dmesg - string containing raw dmesg buffer
126 message_level - minimum message priority to check
127 whitelist - messages to ignore
128
129 Returns:
130 List of unexpected warnings
131 """
Vadim Bendeburye7970922011-04-07 17:07:37 -0700132 whitelist_re = re.compile(r'(%s)' % '|'.join(whitelist))
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -0800133 unexpected = []
134 for line in dmesg.splitlines():
135 if int(line[1]) <= message_level:
Vadim Bendeburye7970922011-04-07 17:07:37 -0700136 stripped_line = line.split('] ', 1)[1]
137 if whitelist_re.search(stripped_line):
138 continue
139 unexpected.append(stripped_line)
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -0800140 return unexpected
Vadim Bendebury29916f22011-04-13 10:54:47 -0700141
142def verify_mesg_set(mesg, regex, whitelist):
143 """Verifies that the exact set of messages are present in a text.
144
145 This function finds all strings in the text matching a certain regex, and
146 then verifies that all expected strings are present in the set, and no
147 unexpected strings are there.
148
149 Arguments:
150 mesg - the mutiline text to be scanned
151 regex - regular expression to match
152 whitelist - messages to find in the output, a list of strings
153 (potentially regexes) to look for in the filtered output. All these
154 strings must be there, and no other strings should be present in the
155 filtered output.
156
157 Returns:
158 string of inconsistent findings (i.e. an empty string on success).
159 """
160
161 rv = []
162
163 missing_strings = []
164 present_strings = []
165 for line in mesg.splitlines():
166 if not re.search(r'%s' % regex, line):
167 continue
168 present_strings.append(line.split('] ', 1)[1])
169
170 for string in whitelist:
171 for present_string in list(present_strings):
172 if re.search(r'^%s$' % string, present_string):
173 present_strings.remove(present_string)
174 break
175 else:
176 missing_strings.append(string)
177
178 if present_strings:
179 rv.append('unexpected strings:')
180 rv.extend(present_strings)
181 if missing_strings:
182 rv.append('missing strings:')
183 rv.extend(missing_strings)
184
185 return '\n'.join(rv)
Ahmad Shariff8e92622011-05-24 12:37:39 -0700186
187
Mike Frysingere72f7e42012-03-16 14:49:11 -0400188def target_is_pie():
189 """Returns whether the toolchain produces a PIE (position independent
Ahmad Shariff8e92622011-05-24 12:37:39 -0700190 executable) by default.
191
192 Arguments:
193 None
194
195 Returns:
Mike Frysingere72f7e42012-03-16 14:49:11 -0400196 True if the target toolchain produces a PIE by default.
Ahmad Shariff8e92622011-05-24 12:37:39 -0700197 False otherwise.
198 """
199
200
Mike Frysingere72f7e42012-03-16 14:49:11 -0400201 command = 'echo | ${CC} -E -dD -P - | grep -i pie'
Ahmad Shariff8e92622011-05-24 12:37:39 -0700202 result = utils.system_output(command, retain_output=True,
203 ignore_status=True)
Mike Frysingere72f7e42012-03-16 14:49:11 -0400204 if re.search('#define __PIE__', result):
Ahmad Shariff8e92622011-05-24 12:37:39 -0700205 return True
206 else:
207 return False
Elly Jones686c2f42011-10-24 16:45:07 -0400208
Sonny Rao172edad2012-02-07 23:23:58 +0000209def target_is_x86():
210 """Returns whether the toolchain produces an x86 object
211
212 Arguments:
213 None
214
215 Returns:
216 True if the target toolchain produces an x86 object
217 False otherwise.
218 """
219
220
Mike Frysingere72f7e42012-03-16 14:49:11 -0400221 command = 'echo | ${CC} -E -dD -P - | grep -i 86'
Sonny Rao172edad2012-02-07 23:23:58 +0000222 result = utils.system_output(command, retain_output=True,
223 ignore_status=True)
Mike Frysingere72f7e42012-03-16 14:49:11 -0400224 if re.search('__i386__', result) or re.search('__x86_64__', result):
Sonny Rao172edad2012-02-07 23:23:58 +0000225 return True
226 else:
227 return False
228
Elly Jones686c2f42011-10-24 16:45:07 -0400229def mounts():
230 ret = []
231 for line in file('/proc/mounts'):
232 m = re.match(r'(?P<src>\S+) (?P<dest>\S+) (?P<type>\S+) (?P<opts>\S+).*', line)
233 if m:
234 ret.append(m.groupdict())
235 return ret
236
237def is_mountpoint(path):
238 return path in [ m['dest'] for m in mounts() ]
239
240def require_mountpoint(path):
241 """
242 Raises an exception if path is not a mountpoint.
243 """
244 if not is_mountpoint(path):
245 raise error.TestFail('Path not mounted: "%s"' % path)
Elly Jones2f0ebba2011-10-27 13:43:20 -0400246
247def random_username():
248 return str(uuid.uuid4()) + '@example.com'