blob: deb96ec0c04c3a1b6a2a816b7a847383f2cba7a8 [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
62 condition: function taking no args and returning bool
63 exception: exception to throw if condition doesn't become true
64 timeout: maximum number of seconds to wait
65 sleep_interval: time to sleep between polls
rgindaf25f73f2010-04-07 14:55:25 -070066 desc: description of default TimeoutError used if 'exception' is None
Daniel Erat3e3f7f42010-03-29 17:19:14 -070067
68 Raises:
rgindaf25f73f2010-04-07 14:55:25 -070069 'exception' arg if supplied; site_utils.TimeoutError otherwise
Daniel Erat3e3f7f42010-03-29 17:19:14 -070070 """
71 start_time = time.time()
72 while True:
73 if condition():
74 return
75 if time.time() + sleep_interval - start_time > timeout:
rgindaf25f73f2010-04-07 14:55:25 -070076 if exception:
Gaurav Shaha7fb8962011-08-16 15:06:32 -070077 logging.error(exception)
rgindaf25f73f2010-04-07 14:55:25 -070078 raise exception
79
80 if desc:
81 desc = 'Timed out waiting for condition: %s' % desc
82 else:
83 desc = 'Timed out waiting for unnamed condition'
Gaurav Shaha7fb8962011-08-16 15:06:32 -070084 logging.error(desc)
Mitsuru Oshima5d3e4542010-08-18 13:46:06 -070085 raise TimeoutError, desc
rgindaf25f73f2010-04-07 14:55:25 -070086
Daniel Erat3e3f7f42010-03-29 17:19:14 -070087 time.sleep(sleep_interval)
Thieu Le1904d002010-11-30 17:10:24 -080088
89
90def save_vm_state(checkpoint):
91 """Saves the current state of the virtual machine.
92
93 This function is a NOOP if the test is not running under a virtual machine
94 with the USB serial port redirected.
95
96 Arguments:
97 checkpoint - Name used to identify this state
98
99 Returns:
100 None
101 """
102 # The QEMU monitor has been redirected to the guest serial port located at
103 # /dev/ttyUSB0. To save the state of the VM, we just send the 'savevm'
104 # command to the serial port.
105 proc = platform.processor()
106 if 'QEMU' in proc and os.path.exists('/dev/ttyUSB0'):
107 logging.info('Saving VM state "%s"' % checkpoint)
108 serial = open('/dev/ttyUSB0', 'w')
109 serial.write("savevm %s\r\n" % checkpoint)
110 logging.info('Done saving VM state "%s"' % checkpoint)
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -0800111
112
113def check_raw_dmesg(dmesg, message_level, whitelist):
114 """Checks dmesg for unexpected warnings.
115
116 This function parses dmesg for message with message_level <= message_level
117 which do not appear in the whitelist.
118
119 Arguments:
120 dmesg - string containing raw dmesg buffer
121 message_level - minimum message priority to check
122 whitelist - messages to ignore
123
124 Returns:
125 List of unexpected warnings
126 """
Vadim Bendeburye7970922011-04-07 17:07:37 -0700127 whitelist_re = re.compile(r'(%s)' % '|'.join(whitelist))
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -0800128 unexpected = []
129 for line in dmesg.splitlines():
130 if int(line[1]) <= message_level:
Vadim Bendeburye7970922011-04-07 17:07:37 -0700131 stripped_line = line.split('] ', 1)[1]
132 if whitelist_re.search(stripped_line):
133 continue
134 unexpected.append(stripped_line)
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -0800135 return unexpected
Vadim Bendebury29916f22011-04-13 10:54:47 -0700136
137def verify_mesg_set(mesg, regex, whitelist):
138 """Verifies that the exact set of messages are present in a text.
139
140 This function finds all strings in the text matching a certain regex, and
141 then verifies that all expected strings are present in the set, and no
142 unexpected strings are there.
143
144 Arguments:
145 mesg - the mutiline text to be scanned
146 regex - regular expression to match
147 whitelist - messages to find in the output, a list of strings
148 (potentially regexes) to look for in the filtered output. All these
149 strings must be there, and no other strings should be present in the
150 filtered output.
151
152 Returns:
153 string of inconsistent findings (i.e. an empty string on success).
154 """
155
156 rv = []
157
158 missing_strings = []
159 present_strings = []
160 for line in mesg.splitlines():
161 if not re.search(r'%s' % regex, line):
162 continue
163 present_strings.append(line.split('] ', 1)[1])
164
165 for string in whitelist:
166 for present_string in list(present_strings):
167 if re.search(r'^%s$' % string, present_string):
168 present_strings.remove(present_string)
169 break
170 else:
171 missing_strings.append(string)
172
173 if present_strings:
174 rv.append('unexpected strings:')
175 rv.extend(present_strings)
176 if missing_strings:
177 rv.append('missing strings:')
178 rv.extend(missing_strings)
179
180 return '\n'.join(rv)
Ahmad Shariff8e92622011-05-24 12:37:39 -0700181
182
183def target_is_x86_pie():
184 """Returns whether the toolchain produces an x86 PIE (position independent
185 executable) by default.
186
187 Arguments:
188 None
189
190 Returns:
191 True if the target toolchain produces an x86 PIE by default.
192 False otherwise.
193 """
194
195
196 command = "echo \"int main(){return 0;}\" | ${CC} -o /tmp/a.out -xc -"
197 command += "&& file /tmp/a.out"
198 result = utils.system_output(command, retain_output=True,
199 ignore_status=True)
200 if re.search("80\d86", result) and re.search("shared object", result):
201 return True
202 else:
203 return False
Elly Jones686c2f42011-10-24 16:45:07 -0400204
205def mounts():
206 ret = []
207 for line in file('/proc/mounts'):
208 m = re.match(r'(?P<src>\S+) (?P<dest>\S+) (?P<type>\S+) (?P<opts>\S+).*', line)
209 if m:
210 ret.append(m.groupdict())
211 return ret
212
213def is_mountpoint(path):
214 return path in [ m['dest'] for m in mounts() ]
215
216def require_mountpoint(path):
217 """
218 Raises an exception if path is not a mountpoint.
219 """
220 if not is_mountpoint(path):
221 raise error.TestFail('Path not mounted: "%s"' % path)
Elly Jones2f0ebba2011-10-27 13:43:20 -0400222
223def random_username():
224 return str(uuid.uuid4()) + '@example.com'