blob: 100fe866e867b616c1249d425aae84176935e616 [file] [log] [blame]
Daniel Erat3e3f7f42010-03-29 17:19:14 -07001# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2# 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:
65 raise exception
66
67 if desc:
68 desc = 'Timed out waiting for condition: %s' % desc
69 else:
70 desc = 'Timed out waiting for unnamed condition'
Mitsuru Oshima5d3e4542010-08-18 13:46:06 -070071 raise TimeoutError, desc
rgindaf25f73f2010-04-07 14:55:25 -070072
Daniel Erat3e3f7f42010-03-29 17:19:14 -070073 time.sleep(sleep_interval)
Thieu Le1904d002010-11-30 17:10:24 -080074
75
76def save_vm_state(checkpoint):
77 """Saves the current state of the virtual machine.
78
79 This function is a NOOP if the test is not running under a virtual machine
80 with the USB serial port redirected.
81
82 Arguments:
83 checkpoint - Name used to identify this state
84
85 Returns:
86 None
87 """
88 # The QEMU monitor has been redirected to the guest serial port located at
89 # /dev/ttyUSB0. To save the state of the VM, we just send the 'savevm'
90 # command to the serial port.
91 proc = platform.processor()
92 if 'QEMU' in proc and os.path.exists('/dev/ttyUSB0'):
93 logging.info('Saving VM state "%s"' % checkpoint)
94 serial = open('/dev/ttyUSB0', 'w')
95 serial.write("savevm %s\r\n" % checkpoint)
96 logging.info('Done saving VM state "%s"' % checkpoint)
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -080097
98
99def check_raw_dmesg(dmesg, message_level, whitelist):
100 """Checks dmesg for unexpected warnings.
101
102 This function parses dmesg for message with message_level <= message_level
103 which do not appear in the whitelist.
104
105 Arguments:
106 dmesg - string containing raw dmesg buffer
107 message_level - minimum message priority to check
108 whitelist - messages to ignore
109
110 Returns:
111 List of unexpected warnings
112 """
Vadim Bendeburye7970922011-04-07 17:07:37 -0700113 whitelist_re = re.compile(r'(%s)' % '|'.join(whitelist))
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -0800114 unexpected = []
115 for line in dmesg.splitlines():
116 if int(line[1]) <= message_level:
Vadim Bendeburye7970922011-04-07 17:07:37 -0700117 stripped_line = line.split('] ', 1)[1]
118 if whitelist_re.search(stripped_line):
119 continue
120 unexpected.append(stripped_line)
Mandeep Singh Baines142ac8d2011-02-18 13:31:08 -0800121 return unexpected
Vadim Bendebury29916f22011-04-13 10:54:47 -0700122
123def verify_mesg_set(mesg, regex, whitelist):
124 """Verifies that the exact set of messages are present in a text.
125
126 This function finds all strings in the text matching a certain regex, and
127 then verifies that all expected strings are present in the set, and no
128 unexpected strings are there.
129
130 Arguments:
131 mesg - the mutiline text to be scanned
132 regex - regular expression to match
133 whitelist - messages to find in the output, a list of strings
134 (potentially regexes) to look for in the filtered output. All these
135 strings must be there, and no other strings should be present in the
136 filtered output.
137
138 Returns:
139 string of inconsistent findings (i.e. an empty string on success).
140 """
141
142 rv = []
143
144 missing_strings = []
145 present_strings = []
146 for line in mesg.splitlines():
147 if not re.search(r'%s' % regex, line):
148 continue
149 present_strings.append(line.split('] ', 1)[1])
150
151 for string in whitelist:
152 for present_string in list(present_strings):
153 if re.search(r'^%s$' % string, present_string):
154 present_strings.remove(present_string)
155 break
156 else:
157 missing_strings.append(string)
158
159 if present_strings:
160 rv.append('unexpected strings:')
161 rv.extend(present_strings)
162 if missing_strings:
163 rv.append('missing strings:')
164 rv.extend(missing_strings)
165
166 return '\n'.join(rv)
Ahmad Shariff8e92622011-05-24 12:37:39 -0700167
168
169def target_is_x86_pie():
170 """Returns whether the toolchain produces an x86 PIE (position independent
171 executable) by default.
172
173 Arguments:
174 None
175
176 Returns:
177 True if the target toolchain produces an x86 PIE by default.
178 False otherwise.
179 """
180
181
182 command = "echo \"int main(){return 0;}\" | ${CC} -o /tmp/a.out -xc -"
183 command += "&& file /tmp/a.out"
184 result = utils.system_output(command, retain_output=True,
185 ignore_status=True)
186 if re.search("80\d86", result) and re.search("shared object", result):
187 return True
188 else:
189 return False