blob: fe4c75e6004bc4e42294de6691a3c2f0892fb9e4 [file] [log] [blame]
barfab@chromium.orgb6d29932012-04-11 09:46:43 +02001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Ken Mixter20d9e472010-08-12 10:58:46 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Dale Curtis497c2cb2010-11-16 13:44:33 -08005import logging, os, re, shutil
barfab@chromium.orgb6d29932012-04-11 09:46:43 +02006
7import common, cros_logging
Eric Lie7c4cab2011-01-05 14:39:19 -08008from autotest_lib.client.bin import test, utils
9from autotest_lib.client.common_lib import error
Ken Mixter20d9e472010-08-12 10:58:46 -070010
11
12class CrashTest(test.test):
Simon Glassa47f0d72011-03-15 11:45:32 -070013 """
14 This class deals with running crash tests, which are tests which crash a
15 user-space program (or the whole machine) and generate a core dump. We
16 want to check that the correct crash dump is available and can be
17 retrieved.
18
19 Chromium OS has a crash sender which checks for new crash data and sends
20 it to a server. This crash data is used to track software quality and find
21 bugs. The system crash sender normally is always running, but can be paused
22 by creating _PAUSE_FILE. When crash sender sees this, it pauses operation.
23
24 The pid of the system crash sender is stored in _CRASH_SENDER_RUN_PATH so
25 we can use this to kill the system crash sender for when we want to run
26 our own.
27
28 For testing purposes we sometimes want to run the crash sender manually.
29 In this case we can set 'OVERRIDE_PAUSE_SENDING=1' in the environment and
30 run the crash sender manually (as a child process).
31
32 Also for testing we sometimes want to mock out the crash sender, and just
33 have it pretend to succeed or fail. The _MOCK_CRASH_SENDING file is used
34 for this. If it doesn't exist, then the crash sender runs normally. If
35 it exists but is empty, the crash sender will succeed (but actually do
36 nothing). If the file contains something, then the crash sender will fail.
37
38 If the user consents to sending crash tests, then the _CONSENT_FILE will
39 exist in the home directory. This test needs to create this file for the
40 crash sending to work.
41
42 Crash reports are rate limited to a certain number of reports each 24
43 hours. If the maximum number has already been sent then reports are held
44 until later. This is administered by a directory _CRASH_SENDER_RATE_DIR
45 which contains one temporary file for each time a report is sent.
46
47 The class provides the ability to push a consent file. This disables
48 consent for this test but allows it to be popped back at later. This
49 makes nested tests easier. If _automatic_consent_saving is True (the
50 default) then consent will be pushed at the start and popped at the end.
51
52 Interesting variables:
53 _log_reader: the log reader used for reading log files
54 _leave_crash_sending: True to enable crash sending on exit from the
55 test, False to disable it. (Default True).
56 _automatic_consent_saving: True to push the consent at the start of
57 the test and pop it afterwards. (Default True).
58
59 Useful places to look for more information are:
60
61 chromeos/src/platform/crash-reporter/crash_sender
62 - sender script which crash crash reporter to create reports, then
63
64 chromeos/src/platform/crash-reporter/
65 - crash reporter program
66 """
67
Ken Mixter20d9e472010-08-12 10:58:46 -070068
69 _CONSENT_FILE = '/home/chronos/Consent To Send Stats'
Julian Pastarmovd56badb2011-07-15 20:24:45 +020070 _POLICY_FILE = '/var/lib/whitelist/policy'
71 _OWNER_KEY_FILE = '/var/lib/whitelist/owner.key'
Ken Mixterddcd92d2010-11-01 19:07:08 -070072 _CORE_PATTERN = '/proc/sys/kernel/core_pattern'
Ken Mixter20d9e472010-08-12 10:58:46 -070073 _CRASH_REPORTER_PATH = '/sbin/crash_reporter'
74 _CRASH_SENDER_PATH = '/sbin/crash_sender'
75 _CRASH_SENDER_RATE_DIR = '/var/lib/crash_sender'
76 _CRASH_SENDER_RUN_PATH = '/var/run/crash_sender.pid'
Thieu Lec16253b2011-03-03 11:13:54 -080077 _CRASH_TEST_IN_PROGRESS = '/tmp/crash-test-in-progress'
Ken Mixter20d9e472010-08-12 10:58:46 -070078 _MOCK_CRASH_SENDING = '/tmp/mock-crash-sending'
Ken Mixter38dfe852010-08-18 15:24:00 -070079 _PAUSE_FILE = '/var/lib/crash_sender_paused'
Ken Mixter20d9e472010-08-12 10:58:46 -070080 _SYSTEM_CRASH_DIR = '/var/spool/crash'
Mike Frysingerded8de72013-05-29 20:45:48 -040081 _FALLBACK_USER_CRASH_DIR = '/home/chronos/crash'
82 _USER_CRASH_DIRS = '/home/chronos/u-*/crash'
Ken Mixter20d9e472010-08-12 10:58:46 -070083
Mike Frysingerbb54bc82014-05-14 14:04:56 -040084 # Use the same file format as crash does normally:
85 # <basename>.#.#.#.meta
86 _FAKE_TEST_BASENAME = 'fake.1.2.3'
87
Ken Mixter4f619652010-10-18 12:11:18 -070088 def _set_system_sending(self, is_enabled):
89 """Sets whether or not the system crash_sender is allowed to run.
90
Simon Glassa47f0d72011-03-15 11:45:32 -070091 This is done by creating or removing _PAUSE_FILE.
92
Ken Mixter4f619652010-10-18 12:11:18 -070093 crash_sender may still be allowed to run if _set_child_sending is
Simon Glassa47f0d72011-03-15 11:45:32 -070094 called with True and it is run as a child process.
95
96 Args:
97 is_enabled: True to enable crash_sender, False to disable it.
98 """
Ken Mixter20d9e472010-08-12 10:58:46 -070099 if is_enabled:
100 if os.path.exists(self._PAUSE_FILE):
101 os.remove(self._PAUSE_FILE)
102 else:
103 utils.system('touch ' + self._PAUSE_FILE)
104
105
Ken Mixter4f619652010-10-18 12:11:18 -0700106 def _set_child_sending(self, is_enabled):
Simon Glassa47f0d72011-03-15 11:45:32 -0700107 """Overrides crash sending enabling for child processes.
108
109 When the system crash sender is disabled this test can manually run
110 the crash sender as a child process. Normally this would do nothing,
111 but this function sets up crash_sender to ignore its disabled status
112 and do its job.
113
114 Args:
115 is_enabled: True to enable crash sending for child processes.
116 """
Ken Mixter4f619652010-10-18 12:11:18 -0700117 if is_enabled:
118 os.environ['OVERRIDE_PAUSE_SENDING'] = "1"
119 else:
120 del os.environ['OVERRIDE_PAUSE_SENDING']
121
122
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700123 def _set_force_official(self, is_enabled):
124 """Sets whether or not reports will upload for unofficial versions.
125
126 Normally, crash reports are only uploaded for official build
127 versions. If the override is set, however, they will also be
128 uploaded for unofficial versions.
129
130 Args:
131 is_enabled: True to enable uploading for unofficial versions.
132 """
133 if is_enabled:
134 os.environ['FORCE_OFFICIAL'] = "1"
135 elif os.environ.get('FORCE_OFFICIAL'):
136 del os.environ['FORCE_OFFICIAL']
137
138
Michael Krebsfb875d02012-09-13 16:49:50 -0700139 def _set_mock_developer_mode(self, is_enabled):
140 """Sets whether or not we should pretend we booted in developer mode.
141
142 Args:
143 is_enabled: True to pretend we are in developer mode.
144 """
145 if is_enabled:
146 os.environ['MOCK_DEVELOPER_MODE'] = "1"
147 elif os.environ.get('MOCK_DEVELOPER_MODE'):
148 del os.environ['MOCK_DEVELOPER_MODE']
149
150
Ken Mixter20d9e472010-08-12 10:58:46 -0700151 def _reset_rate_limiting(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700152 """Reset the count of crash reports sent today.
153
154 This clears the contents of the rate limiting directory which has
155 the effect of reseting our count of crash reports sent.
156 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700157 utils.system('rm -rf ' + self._CRASH_SENDER_RATE_DIR)
158
159
160 def _clear_spooled_crashes(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700161 """Clears system and user crash directories.
162
163 This will remove all crash reports which are waiting to be sent.
164 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700165 utils.system('rm -rf ' + self._SYSTEM_CRASH_DIR)
Mike Frysingerded8de72013-05-29 20:45:48 -0400166 utils.system('rm -rf %s %s' % (self._USER_CRASH_DIRS,
167 self._FALLBACK_USER_CRASH_DIR))
Ken Mixter20d9e472010-08-12 10:58:46 -0700168
169
170 def _kill_running_sender(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700171 """Kill the the crash_sender process if running.
172
173 We use the PID file to find the process ID, then kill it with signal 9.
174 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700175 if not os.path.exists(self._CRASH_SENDER_RUN_PATH):
176 return
177 running_pid = int(utils.read_file(self._CRASH_SENDER_RUN_PATH))
178 logging.warning('Detected running crash sender (%d), killing' %
179 running_pid)
180 utils.system('kill -9 %d' % running_pid)
181 os.remove(self._CRASH_SENDER_RUN_PATH)
182
183
184 def _set_sending_mock(self, mock_enabled, send_success=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700185 """Enables / disables mocking of the sending process.
186
187 This uses the _MOCK_CRASH_SENDING file to achieve its aims. See notes
188 at the top.
189
190 Args:
191 mock_enabled: If True, mocking is enabled, else it is disabled.
192 send_success: If mock_enabled this is True for the mocking to
193 indicate success, False to indicate failure.
194 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700195 if mock_enabled:
196 if send_success:
197 data = ''
198 else:
199 data = '1'
200 logging.info('Setting sending mock')
201 utils.open_write_close(self._MOCK_CRASH_SENDING, data)
202 else:
203 utils.system('rm -f ' + self._MOCK_CRASH_SENDING)
204
205
206 def _set_consent(self, has_consent):
Simon Glassa47f0d72011-03-15 11:45:32 -0700207 """Sets whether or not we have consent to send crash reports.
208
209 This creates or deletes the _CONSENT_FILE to control whether
210 crash_sender will consider that it has consent to send crash reports.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200211 It also copies a policy blob with the proper policy setting.
Simon Glassa47f0d72011-03-15 11:45:32 -0700212
213 Args:
214 has_consent: True to indicate consent, False otherwise
215 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700216 if has_consent:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700217 # Create policy file that enables metrics/consent.
218 shutil.copy('/usr/local/autotest/cros/mock_metrics_on.policy',
219 self._POLICY_FILE)
220 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
221 self._OWNER_KEY_FILE)
222 # Create deprecated consent file. This is created *after* the
223 # policy file in order to avoid a race condition where chrome
224 # might remove the consent file if the policy's not set yet.
Michael Krebse9028fc2011-08-19 15:00:00 -0700225 # We create it as a temp file first in order to make the creation
226 # of the consent file, owned by chronos, atomic.
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700227 # See crosbug.com/18413.
Michael Krebse9028fc2011-08-19 15:00:00 -0700228 temp_file = self._CONSENT_FILE + '.tmp';
229 utils.open_write_close(temp_file, 'test-consent')
230 utils.system('chown chronos:chronos "%s"' % (temp_file))
231 shutil.move(temp_file, self._CONSENT_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700232 logging.info('Created ' + self._CONSENT_FILE)
233 else:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700234 # Create policy file that disables metrics/consent.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200235 shutil.copy('/usr/local/autotest/cros/mock_metrics_off.policy',
236 self._POLICY_FILE)
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700237 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
238 self._OWNER_KEY_FILE)
239 # Remove deprecated consent file.
240 utils.system('rm -f "%s"' % (self._CONSENT_FILE))
Ken Mixter20d9e472010-08-12 10:58:46 -0700241
242
Thieu Lec16253b2011-03-03 11:13:54 -0800243 def _set_crash_test_in_progress(self, in_progress):
244 if in_progress:
245 utils.open_write_close(self._CRASH_TEST_IN_PROGRESS, 'in-progress')
246 logging.info('Created ' + self._CRASH_TEST_IN_PROGRESS)
247 else:
248 utils.system('rm -f "%s"' % (self._CRASH_TEST_IN_PROGRESS))
249
250
Ken Mixter20d9e472010-08-12 10:58:46 -0700251 def _get_pushed_consent_file_path(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700252 """Returns filename of the pushed consent file."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700253 return os.path.join(self.bindir, 'pushed_consent')
254
255
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200256 def _get_pushed_policy_file_path(self):
257 """Returns filename of the pushed policy file."""
258 return os.path.join(self.bindir, 'pushed_policy')
259
260
261 def _get_pushed_owner_key_file_path(self):
262 """Returns filename of the pushed owner.key file."""
263 return os.path.join(self.bindir, 'pushed_owner_key')
264
265
Ken Mixter20d9e472010-08-12 10:58:46 -0700266 def _push_consent(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700267 """Push the consent file, thus disabling consent.
268
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200269 The consent files can be created in the new test if required. Call
Simon Glassa47f0d72011-03-15 11:45:32 -0700270 _pop_consent() to restore the original state.
271 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700272 if os.path.exists(self._CONSENT_FILE):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800273 shutil.move(self._CONSENT_FILE,
274 self._get_pushed_consent_file_path())
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200275 if os.path.exists(self._POLICY_FILE):
276 shutil.move(self._POLICY_FILE,
277 self._get_pushed_policy_file_path())
278 if os.path.exists(self._OWNER_KEY_FILE):
279 shutil.move(self._OWNER_KEY_FILE,
280 self._get_pushed_owner_key_file_path())
Ken Mixter20d9e472010-08-12 10:58:46 -0700281
282
283 def _pop_consent(self):
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200284 """Pop the consent files, enabling/disabling consent as it was before
Simon Glassa47f0d72011-03-15 11:45:32 -0700285 we pushed the consent."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700286 if os.path.exists(self._get_pushed_consent_file_path()):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800287 shutil.move(self._get_pushed_consent_file_path(),
288 self._CONSENT_FILE)
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200289 else:
290 utils.system('rm -f "%s"' % self._CONSENT_FILE)
291 if os.path.exists(self._get_pushed_policy_file_path()):
292 shutil.move(self._get_pushed_policy_file_path(),
293 self._POLICY_FILE)
294 else:
295 utils.system('rm -f "%s"' % self._POLICY_FILE)
296 if os.path.exists(self._get_pushed_owner_key_file_path()):
297 shutil.move(self._get_pushed_owner_key_file_path(),
298 self._OWNER_KEY_FILE)
299 else:
300 utils.system('rm -f "%s"' % self._OWNER_KEY_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700301
302
303 def _get_crash_dir(self, username):
Simon Glassa47f0d72011-03-15 11:45:32 -0700304 """Returns full path to the crash directory for a given username
305
Mike Frysingerded8de72013-05-29 20:45:48 -0400306 This only really works (currently) when no one is logged in. That
307 is OK (currently) as the only test that uses this runs when no one
308 is actually logged in.
309
Simon Glassa47f0d72011-03-15 11:45:32 -0700310 Args:
311 username: username to use:
312 'chronos': Returns user crash directory.
313 'root': Returns system crash directory.
314 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700315 if username == 'chronos':
Mike Frysingerded8de72013-05-29 20:45:48 -0400316 return self._FALLBACK_USER_CRASH_DIR
Ken Mixter20d9e472010-08-12 10:58:46 -0700317 else:
318 return self._SYSTEM_CRASH_DIR
319
320
321 def _initialize_crash_reporter(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700322 """Start up the crash reporter."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700323 utils.system('%s --init --nounclean_check' % self._CRASH_REPORTER_PATH)
Ken Mixterddcd92d2010-11-01 19:07:08 -0700324 # Completely disable crash_reporter from generating crash dumps
325 # while any tests are running, otherwise a crashy system can make
326 # these tests flaky.
327 self.enable_crash_filtering('none')
Ken Mixter20d9e472010-08-12 10:58:46 -0700328
329
Mike Frysingerbb54bc82014-05-14 14:04:56 -0400330 def get_crash_dir_name(self, name):
331 """Return the full path for |name| inside the system crash directory."""
332 return os.path.join(self._SYSTEM_CRASH_DIR, name)
333
334
Ken Mixter67ff5622010-09-30 15:32:17 -0700335 def write_crash_dir_entry(self, name, contents):
Simon Glassa47f0d72011-03-15 11:45:32 -0700336 """Writes an empty file to the system crash directory.
337
338 This writes a file to _SYSTEM_CRASH_DIR with the given name. This is
339 used to insert new crash dump files for testing purposes.
340
341 Args:
342 name: Name of file to write.
343 contents: String to write to the file.
344 """
Mike Frysingerbb54bc82014-05-14 14:04:56 -0400345 entry = self.get_crash_dir_name(name)
Ken Mixter20d9e472010-08-12 10:58:46 -0700346 if not os.path.exists(self._SYSTEM_CRASH_DIR):
347 os.makedirs(self._SYSTEM_CRASH_DIR)
Ken Mixter67ff5622010-09-30 15:32:17 -0700348 utils.open_write_close(entry, contents)
Ken Mixter20d9e472010-08-12 10:58:46 -0700349 return entry
350
351
Ken Mixterdee4e292010-12-14 17:45:21 -0800352 def write_fake_meta(self, name, exec_name, payload, log=None,
353 complete=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700354 """Writes a fake meta entry to the system crash directory.
355
356 Args:
357 name: Name of file to write.
358 exec_name: Value for exec_name item.
359 payload: Value for payload item.
360 log: Value for log item.
361 complete: True to close off the record, otherwise leave it
362 incomplete.
363 """
Ken Mixter1a894e02010-10-28 15:42:52 -0700364 last_line = ''
365 if complete:
366 last_line = 'done=1\n'
Ken Mixterdee4e292010-12-14 17:45:21 -0800367 contents = ('exec_name=%s\n'
368 'ver=my_ver\n'
369 'payload=%s\n'
370 '%s' % (exec_name, payload,
371 last_line))
372 if log:
373 contents = ('log=%s\n' % log) + contents
374 return self.write_crash_dir_entry(name, contents)
Ken Mixter67ff5622010-09-30 15:32:17 -0700375
376
Ken Mixter20d9e472010-08-12 10:58:46 -0700377 def _prepare_sender_one_crash(self,
378 send_success,
379 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700380 report):
Simon Glassa47f0d72011-03-15 11:45:32 -0700381 """Create metadata for a fake crash report.
382
383 This enabled mocking of the crash sender, then creates a fake
384 crash report for testing purposes.
385
386 Args:
387 send_success: True to make the crash_sender success, False to make
388 it fail.
389 reports_enabled: True to enable consent to that reports will be
390 sent.
391 report: Report to use for crash, if None we create one.
392 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700393 self._set_sending_mock(mock_enabled=True, send_success=send_success)
394 self._set_consent(reports_enabled)
Ken Mixter38dfe852010-08-18 15:24:00 -0700395 if report is None:
Mike Frysingerbb54bc82014-05-14 14:04:56 -0400396 # Use the same file format as crash does normally:
397 # <basename>.#.#.#.meta
398 payload = self.write_crash_dir_entry(
399 '%s.dmp' % self._FAKE_TEST_BASENAME, '')
400 report = self.write_fake_meta(
401 '%s.meta' % self._FAKE_TEST_BASENAME, 'fake', payload)
Ken Mixter38dfe852010-08-18 15:24:00 -0700402 return report
Ken Mixter20d9e472010-08-12 10:58:46 -0700403
404
405 def _parse_sender_output(self, output):
406 """Parse the log output from the crash_sender script.
407
408 This script can run on the logs from either a mocked or true
409 crash send.
410
411 Args:
412 output: output from the script
413
414 Returns:
415 A dictionary with these values:
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700416 error_type: an error type, if given
Ken Mixter38dfe852010-08-18 15:24:00 -0700417 exec_name: name of executable which crashed
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700418 image_type: type of image ("dev","force-official",...), if given
Michael Krebsfb875d02012-09-13 16:49:50 -0700419 boot_mode: current boot mode ("dev",...), if given
Ken Mixter67ff5622010-09-30 15:32:17 -0700420 meta_path: path to the report metadata file
421 output: the output from the script, copied
Ken Mixter38dfe852010-08-18 15:24:00 -0700422 report_kind: kind of report sent (minidump vs kernel)
Ken Mixter20d9e472010-08-12 10:58:46 -0700423 send_attempt: did the script attempt to send a crash.
424 send_success: if it attempted, was the crash send successful.
Ken Mixterd79140e2010-10-26 14:45:30 -0700425 sig: signature of the report, if given.
Ken Mixter20d9e472010-08-12 10:58:46 -0700426 sleep_time: if it attempted, how long did it sleep before
427 sending (if mocked, how long would it have slept)
Ken Mixter20d9e472010-08-12 10:58:46 -0700428 """
429 sleep_match = re.search('Scheduled to send in (\d+)s', output)
430 send_attempt = sleep_match is not None
431 if send_attempt:
432 sleep_time = int(sleep_match.group(1))
433 else:
434 sleep_time = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700435
Ken Mixter67ff5622010-09-30 15:32:17 -0700436 meta_match = re.search('Metadata: (\S+) \((\S+)\)', output)
437 if meta_match:
438 meta_path = meta_match.group(1)
439 report_kind = meta_match.group(2)
Ken Mixter38dfe852010-08-18 15:24:00 -0700440 else:
Ken Mixter67ff5622010-09-30 15:32:17 -0700441 meta_path = None
Ken Mixter38dfe852010-08-18 15:24:00 -0700442 report_kind = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700443
Ken Mixter67ff5622010-09-30 15:32:17 -0700444 payload_match = re.search('Payload: (\S+)', output)
445 if payload_match:
446 report_payload = payload_match.group(1)
447 else:
448 report_payload = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700449
Ken Mixter38dfe852010-08-18 15:24:00 -0700450 exec_name_match = re.search('Exec name: (\S+)', output)
451 if exec_name_match:
452 exec_name = exec_name_match.group(1)
453 else:
454 exec_name = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700455
Ken Mixter10c48672010-11-01 13:37:08 -0700456 sig_match = re.search('sig: (\S+)', output)
Ken Mixterd79140e2010-10-26 14:45:30 -0700457 if sig_match:
458 sig = sig_match.group(1)
459 else:
460 sig = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700461
462 error_type_match = re.search('Error type: (\S+)', output)
463 if error_type_match:
464 error_type = error_type_match.group(1)
465 else:
466 error_type = None
467
468 image_type_match = re.search('Image type: (\S+)', output)
469 if image_type_match:
470 image_type = image_type_match.group(1)
471 else:
472 image_type = None
473
Michael Krebsfb875d02012-09-13 16:49:50 -0700474 boot_mode_match = re.search('Boot mode: (\S+)', output)
475 if boot_mode_match:
476 boot_mode = boot_mode_match.group(1)
477 else:
478 boot_mode = None
479
Ken Mixter20d9e472010-08-12 10:58:46 -0700480 send_success = 'Mocking successful send' in output
Ken Mixter38dfe852010-08-18 15:24:00 -0700481 return {'exec_name': exec_name,
482 'report_kind': report_kind,
Ken Mixter67ff5622010-09-30 15:32:17 -0700483 'meta_path': meta_path,
484 'report_payload': report_payload,
Ken Mixter38dfe852010-08-18 15:24:00 -0700485 'send_attempt': send_attempt,
Ken Mixter20d9e472010-08-12 10:58:46 -0700486 'send_success': send_success,
Ken Mixterd79140e2010-10-26 14:45:30 -0700487 'sig': sig,
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700488 'error_type': error_type,
489 'image_type': image_type,
Michael Krebsfb875d02012-09-13 16:49:50 -0700490 'boot_mode': boot_mode,
Ken Mixter20d9e472010-08-12 10:58:46 -0700491 'sleep_time': sleep_time,
492 'output': output}
493
494
Ken Mixter654f32e2010-10-20 11:47:31 -0700495 def wait_for_sender_completion(self):
496 """Wait for crash_sender to complete.
497
498 Wait for no crash_sender's last message to be placed in the
499 system log before continuing and for the process to finish.
500 Otherwise we might get only part of the output."""
Eric Lie7c4cab2011-01-05 14:39:19 -0800501 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700502 lambda: self._log_reader.can_find('crash_sender done.'),
503 timeout=60,
504 exception=error.TestError(
505 'Timeout waiting for crash_sender to emit done: ' +
506 self._log_reader.get_logs()))
Eric Lie7c4cab2011-01-05 14:39:19 -0800507 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700508 lambda: utils.system('pgrep crash_sender',
509 ignore_status=True) != 0,
510 timeout=60,
511 exception=error.TestError(
512 'Timeout waiting for crash_sender to finish: ' +
513 self._log_reader.get_logs()))
514
515
Ken Mixter20d9e472010-08-12 10:58:46 -0700516 def _call_sender_one_crash(self,
517 send_success=True,
518 reports_enabled=True,
519 username='root',
Ken Mixter38dfe852010-08-18 15:24:00 -0700520 report=None):
Ken Mixter20d9e472010-08-12 10:58:46 -0700521 """Call the crash sender script to mock upload one crash.
522
523 Args:
524 send_success: Mock a successful send if true
525 reports_enabled: Has the user consented to sending crash reports.
526 username: user to emulate a crash from
Ken Mixter38dfe852010-08-18 15:24:00 -0700527 report: report to use for crash, if None we create one.
Ken Mixter20d9e472010-08-12 10:58:46 -0700528
529 Returns:
530 Returns a dictionary describing the result with the keys
531 from _parse_sender_output, as well as:
Ken Mixter38dfe852010-08-18 15:24:00 -0700532 report_exists: does the minidump still exist after calling
Ken Mixter20d9e472010-08-12 10:58:46 -0700533 send script
534 rate_count: how many crashes have been uploaded in the past
535 24 hours.
536 """
Ken Mixter38dfe852010-08-18 15:24:00 -0700537 report = self._prepare_sender_one_crash(send_success,
538 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700539 report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700540 self._log_reader.set_start_by_current()
541 script_output = utils.system_output(
542 '/bin/sh -c "%s" 2>&1' % self._CRASH_SENDER_PATH,
543 ignore_status=True)
Ken Mixter654f32e2010-10-20 11:47:31 -0700544 self.wait_for_sender_completion()
Ken Mixter20d9e472010-08-12 10:58:46 -0700545 output = self._log_reader.get_logs()
546 logging.debug('Crash sender message output:\n' + output)
547 if script_output != '':
548 raise error.TestFail(
549 'Unexpected crash_sender stdout/stderr: ' + script_output)
550
Ken Mixter38dfe852010-08-18 15:24:00 -0700551 if os.path.exists(report):
552 report_exists = True
553 os.remove(report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700554 else:
Ken Mixter38dfe852010-08-18 15:24:00 -0700555 report_exists = False
Ken Mixter20d9e472010-08-12 10:58:46 -0700556 if os.path.exists(self._CRASH_SENDER_RATE_DIR):
557 rate_count = len(os.listdir(self._CRASH_SENDER_RATE_DIR))
558 else:
559 rate_count = 0
560
561 result = self._parse_sender_output(output)
Ken Mixter38dfe852010-08-18 15:24:00 -0700562 result['report_exists'] = report_exists
Ken Mixter20d9e472010-08-12 10:58:46 -0700563 result['rate_count'] = rate_count
564
565 # Show the result for debugging but remove 'output' key
566 # since it's large and earlier in debug output.
567 debug_result = dict(result)
568 del debug_result['output']
569 logging.debug('Result of send (besides output): %s' % debug_result)
570
571 return result
572
573
Ken Mixterddcd92d2010-11-01 19:07:08 -0700574 def _replace_crash_reporter_filter_in(self, new_parameter):
Simon Glassa47f0d72011-03-15 11:45:32 -0700575 """Replaces the --filter_in= parameter of the crash reporter.
576
577 The kernel is set up to call the crash reporter with the core dump
578 as stdin when a process dies. This function adds a filter to the
579 command line used to call the crash reporter. This is used to ignore
580 crashes in which we have no interest.
581
582 This removes any --filter_in= parameter and optionally replaces it
583 with a new one.
584
585 Args:
586 new_parameter: This is parameter to add to the command line
587 instead of the --filter_in=... that was there.
588 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700589 core_pattern = utils.read_file(self._CORE_PATTERN)[:-1]
590 core_pattern = re.sub('--filter_in=\S*\s*', '',
591 core_pattern).rstrip()
592 if new_parameter:
593 core_pattern += ' ' + new_parameter
594 utils.system('echo "%s" > %s' % (core_pattern, self._CORE_PATTERN))
595
596
597 def enable_crash_filtering(self, name):
Simon Glassa47f0d72011-03-15 11:45:32 -0700598 """Add a --filter_in argument to the kernel core dump cmdline.
599
600 Args:
601 name: Filter text to use. This is passed as a --filter_in
602 argument to the crash reporter.
603 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700604 self._replace_crash_reporter_filter_in('--filter_in=' + name)
605
606
607 def disable_crash_filtering(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700608 """Remove the --filter_in argument from the kernel core dump cmdline.
609
610 Next time the crash reporter is invoked (due to a crash) it will not
611 receive a --filter_in paramter."""
Ken Mixterddcd92d2010-11-01 19:07:08 -0700612 self._replace_crash_reporter_filter_in('')
613
614
Ken Mixter20d9e472010-08-12 10:58:46 -0700615 def initialize(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700616 """Initalize the test."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700617 test.test.initialize(self)
Eric Lie7c4cab2011-01-05 14:39:19 -0800618 self._log_reader = cros_logging.LogReader()
Ken Mixter38dfe852010-08-18 15:24:00 -0700619 self._leave_crash_sending = True
Ken Mixter67ff5622010-09-30 15:32:17 -0700620 self._automatic_consent_saving = True
Ken Mixterddcd92d2010-11-01 19:07:08 -0700621 self.enable_crash_filtering('none')
Thieu Lec16253b2011-03-03 11:13:54 -0800622 self._set_crash_test_in_progress(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700623
624
625 def cleanup(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700626 """Cleanup after the test.
627
628 We reset things back to the way we think they should be. This is
629 intended to allow the system to continue normal operation.
630
631 Some variables silently change the behavior:
632 _automatic_consent_saving: if True, we pop the consent file.
633 _leave_crash_sending: True to enable crash sending, False to
634 disable it
635 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700636 self._reset_rate_limiting()
637 self._clear_spooled_crashes()
Ken Mixter4f619652010-10-18 12:11:18 -0700638 self._set_system_sending(self._leave_crash_sending)
Ken Mixter20d9e472010-08-12 10:58:46 -0700639 self._set_sending_mock(mock_enabled=False)
Ken Mixter67ff5622010-09-30 15:32:17 -0700640 if self._automatic_consent_saving:
641 self._pop_consent()
Ken Mixterddcd92d2010-11-01 19:07:08 -0700642 self.disable_crash_filtering()
Thieu Lec16253b2011-03-03 11:13:54 -0800643 self._set_crash_test_in_progress(False)
Ken Mixter20d9e472010-08-12 10:58:46 -0700644 test.test.cleanup(self)
645
646
Ken Mixter38dfe852010-08-18 15:24:00 -0700647 def run_crash_tests(self,
648 test_names,
649 initialize_crash_reporter=False,
650 clear_spool_first=True,
651 must_run_all=True):
652 """Run crash tests defined in this class.
653
654 Args:
Simon Glassa47f0d72011-03-15 11:45:32 -0700655 test_names: Array of test names.
656 initialize_crash_reporter: Should set up crash reporter for every
657 run.
658 clear_spool_first: Clear all spooled user/system crashes before
659 starting the test.
660 must_run_all: Should make sure every test in this class is
661 mentioned in test_names.
Ken Mixter38dfe852010-08-18 15:24:00 -0700662 """
Ken Mixter67ff5622010-09-30 15:32:17 -0700663 if self._automatic_consent_saving:
664 self._push_consent()
Ken Mixter20d9e472010-08-12 10:58:46 -0700665
Ken Mixter38dfe852010-08-18 15:24:00 -0700666 if must_run_all:
667 # Sanity check test_names is complete
668 for attr in dir(self):
669 if attr.find('_test_') == 0:
670 test_name = attr[6:]
671 if not test_name in test_names:
672 raise error.TestError('Test %s is missing' % test_name)
Ken Mixter20d9e472010-08-12 10:58:46 -0700673
674 for test_name in test_names:
675 logging.info(('=' * 20) + ('Running %s' % test_name) + ('=' * 20))
Ken Mixter38dfe852010-08-18 15:24:00 -0700676 if initialize_crash_reporter:
677 self._initialize_crash_reporter()
Ken Mixter4f619652010-10-18 12:11:18 -0700678 # Disable crash_sender from running, kill off any running ones, but
679 # set environment so crash_sender may run as a child process.
680 self._set_system_sending(False)
681 self._set_child_sending(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700682 self._kill_running_sender()
683 self._reset_rate_limiting()
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700684 # Default to not overriding for unofficial versions.
685 self._set_force_official(False)
Michael Krebsfb875d02012-09-13 16:49:50 -0700686 # Default to not pretending we're in developer mode.
687 self._set_mock_developer_mode(False)
Ken Mixter38dfe852010-08-18 15:24:00 -0700688 if clear_spool_first:
689 self._clear_spooled_crashes()
Simon Glassa47f0d72011-03-15 11:45:32 -0700690
691 # Call the test function
Ken Mixter20d9e472010-08-12 10:58:46 -0700692 getattr(self, '_test_' + test_name)()