blob: 0935c2abecc1c9e14293ff3931956b36f8c76976 [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
Vadim Bendeburye7970922011-04-07 17:07:37 -07005import logging, os, platform, re, tempfile, time
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
9
rgindaf25f73f2010-04-07 14:55:25 -070010class TimeoutError(error.TestError):
11 """Error raised when we time out when waiting on a condition."""
12
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
Daniel Erat3e3f7f42010-03-29 17:19:14 -070046def poll_for_condition(
rgindaf25f73f2010-04-07 14:55:25 -070047 condition, exception=None, timeout=10, sleep_interval=0.1, desc=None):
Daniel Erat3e3f7f42010-03-29 17:19:14 -070048 """Poll until a condition becomes true.
49
50 condition: function taking no args and returning bool
51 exception: exception to throw if condition doesn't become true
52 timeout: maximum number of seconds to wait
53 sleep_interval: time to sleep between polls
rgindaf25f73f2010-04-07 14:55:25 -070054 desc: description of default TimeoutError used if 'exception' is None
Daniel Erat3e3f7f42010-03-29 17:19:14 -070055
56 Raises:
rgindaf25f73f2010-04-07 14:55:25 -070057 'exception' arg if supplied; site_utils.TimeoutError otherwise
Daniel Erat3e3f7f42010-03-29 17:19:14 -070058 """
59 start_time = time.time()
60 while True:
61 if condition():
62 return
63 if time.time() + sleep_interval - start_time > timeout:
rgindaf25f73f2010-04-07 14:55:25 -070064 if exception:
Gaurav Shaha7fb8962011-08-16 15:06:32 -070065 logging.error(exception)
rgindaf25f73f2010-04-07 14:55:25 -070066 raise exception
67
68 if desc:
69 desc = 'Timed out waiting for condition: %s' % desc
70 else:
71 desc = 'Timed out waiting for unnamed condition'
Gaurav Shaha7fb8962011-08-16 15:06:32 -070072 logging.error(desc)
Mitsuru Oshima5d3e4542010-08-18 13:46:06 -070073 raise TimeoutError, desc
rgindaf25f73f2010-04-07 14:55:25 -070074
Daniel Erat3e3f7f42010-03-29 17:19:14 -070075 time.sleep(sleep_interval)
Thieu Le1904d002010-11-30 17:10:24 -080076
77
78def save_vm_state(checkpoint):
79 """Saves the current state of the virtual machine.
80
81 This function is a NOOP if the test is not running under a virtual machine
82 with the USB serial port redirected.
83
84 Arguments:
85 checkpoint - Name used to identify this state
86
87 Returns:
88 None
89 """
90 # The QEMU monitor has been redirected to the guest serial port located at
91 # /dev/ttyUSB0. To save the state of the VM, we just send the 'savevm'
92 # command to the serial port.
93 proc = platform.processor()
94 if 'QEMU' in proc and os.path.exists('/dev/ttyUSB0'):
95 logging.info('Saving VM state "%s"' % checkpoint)
96 serial = open('/dev/ttyUSB0', 'w')
97 serial.write("savevm %s\r\n" % checkpoint)
98 logging.info('Done saving VM state "%s"' % checkpoint)
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -080099
100
101def check_raw_dmesg(dmesg, message_level, whitelist):
102 """Checks dmesg for unexpected warnings.
103
104 This function parses dmesg for message with message_level <= message_level
105 which do not appear in the whitelist.
106
107 Arguments:
108 dmesg - string containing raw dmesg buffer
109 message_level - minimum message priority to check
110 whitelist - messages to ignore
111
112 Returns:
113 List of unexpected warnings
114 """
Vadim Bendeburye7970922011-04-07 17:07:37 -0700115 whitelist_re = re.compile(r'(%s)' % '|'.join(whitelist))
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -0800116 unexpected = []
117 for line in dmesg.splitlines():
118 if int(line[1]) <= message_level:
Vadim Bendeburye7970922011-04-07 17:07:37 -0700119 stripped_line = line.split('] ', 1)[1]
120 if whitelist_re.search(stripped_line):
121 continue
122 unexpected.append(stripped_line)
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -0800123 return unexpected
Vadim Bendebury29916f22011-04-13 10:54:47 -0700124
125def verify_mesg_set(mesg, regex, whitelist):
126 """Verifies that the exact set of messages are present in a text.
127
128 This function finds all strings in the text matching a certain regex, and
129 then verifies that all expected strings are present in the set, and no
130 unexpected strings are there.
131
132 Arguments:
133 mesg - the mutiline text to be scanned
134 regex - regular expression to match
135 whitelist - messages to find in the output, a list of strings
136 (potentially regexes) to look for in the filtered output. All these
137 strings must be there, and no other strings should be present in the
138 filtered output.
139
140 Returns:
141 string of inconsistent findings (i.e. an empty string on success).
142 """
143
144 rv = []
145
146 missing_strings = []
147 present_strings = []
148 for line in mesg.splitlines():
149 if not re.search(r'%s' % regex, line):
150 continue
151 present_strings.append(line.split('] ', 1)[1])
152
153 for string in whitelist:
154 for present_string in list(present_strings):
155 if re.search(r'^%s$' % string, present_string):
156 present_strings.remove(present_string)
157 break
158 else:
159 missing_strings.append(string)
160
161 if present_strings:
162 rv.append('unexpected strings:')
163 rv.extend(present_strings)
164 if missing_strings:
165 rv.append('missing strings:')
166 rv.extend(missing_strings)
167
168 return '\n'.join(rv)
Ahmad Shariff8e92622011-05-24 12:37:39 -0700169
170
171def target_is_x86_pie():
172 """Returns whether the toolchain produces an x86 PIE (position independent
173 executable) by default.
174
175 Arguments:
176 None
177
178 Returns:
179 True if the target toolchain produces an x86 PIE by default.
180 False otherwise.
181 """
182
183
184 command = "echo \"int main(){return 0;}\" | ${CC} -o /tmp/a.out -xc -"
185 command += "&& file /tmp/a.out"
186 result = utils.system_output(command, retain_output=True,
187 ignore_status=True)
188 if re.search("80\d86", result) and re.search("shared object", result):
189 return True
190 else:
191 return False