blob: e7a314cc89e569e6ff50acbec24e2f5ff97e12d9 [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
Mike Frysinger0fa79ab2014-05-24 21:16:04 -04005import contextlib, fcntl, 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'
Mike Frysinger0fa79ab2014-05-24 21:16:04 -040077 _CRASH_SENDER_LOCK_PATH = '/var/lock/crash_sender'
Thieu Lec16253b2011-03-03 11:13:54 -080078 _CRASH_TEST_IN_PROGRESS = '/tmp/crash-test-in-progress'
Ken Mixter20d9e472010-08-12 10:58:46 -070079 _MOCK_CRASH_SENDING = '/tmp/mock-crash-sending'
Ken Mixter38dfe852010-08-18 15:24:00 -070080 _PAUSE_FILE = '/var/lib/crash_sender_paused'
Ken Mixter20d9e472010-08-12 10:58:46 -070081 _SYSTEM_CRASH_DIR = '/var/spool/crash'
Mike Frysingerded8de72013-05-29 20:45:48 -040082 _FALLBACK_USER_CRASH_DIR = '/home/chronos/crash'
83 _USER_CRASH_DIRS = '/home/chronos/u-*/crash'
Ken Mixter20d9e472010-08-12 10:58:46 -070084
Mike Frysingerbb54bc82014-05-14 14:04:56 -040085 # Use the same file format as crash does normally:
86 # <basename>.#.#.#.meta
87 _FAKE_TEST_BASENAME = 'fake.1.2.3'
88
Ken Mixter4f619652010-10-18 12:11:18 -070089 def _set_system_sending(self, is_enabled):
90 """Sets whether or not the system crash_sender is allowed to run.
91
Simon Glassa47f0d72011-03-15 11:45:32 -070092 This is done by creating or removing _PAUSE_FILE.
93
Ken Mixter4f619652010-10-18 12:11:18 -070094 crash_sender may still be allowed to run if _set_child_sending is
Simon Glassa47f0d72011-03-15 11:45:32 -070095 called with True and it is run as a child process.
96
97 Args:
98 is_enabled: True to enable crash_sender, False to disable it.
99 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700100 if is_enabled:
101 if os.path.exists(self._PAUSE_FILE):
102 os.remove(self._PAUSE_FILE)
103 else:
104 utils.system('touch ' + self._PAUSE_FILE)
105
106
Ken Mixter4f619652010-10-18 12:11:18 -0700107 def _set_child_sending(self, is_enabled):
Simon Glassa47f0d72011-03-15 11:45:32 -0700108 """Overrides crash sending enabling for child processes.
109
110 When the system crash sender is disabled this test can manually run
111 the crash sender as a child process. Normally this would do nothing,
112 but this function sets up crash_sender to ignore its disabled status
113 and do its job.
114
115 Args:
116 is_enabled: True to enable crash sending for child processes.
117 """
Ken Mixter4f619652010-10-18 12:11:18 -0700118 if is_enabled:
119 os.environ['OVERRIDE_PAUSE_SENDING'] = "1"
120 else:
121 del os.environ['OVERRIDE_PAUSE_SENDING']
122
123
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700124 def _set_force_official(self, is_enabled):
125 """Sets whether or not reports will upload for unofficial versions.
126
127 Normally, crash reports are only uploaded for official build
128 versions. If the override is set, however, they will also be
129 uploaded for unofficial versions.
130
131 Args:
132 is_enabled: True to enable uploading for unofficial versions.
133 """
134 if is_enabled:
135 os.environ['FORCE_OFFICIAL'] = "1"
136 elif os.environ.get('FORCE_OFFICIAL'):
137 del os.environ['FORCE_OFFICIAL']
138
139
Michael Krebsfb875d02012-09-13 16:49:50 -0700140 def _set_mock_developer_mode(self, is_enabled):
141 """Sets whether or not we should pretend we booted in developer mode.
142
143 Args:
144 is_enabled: True to pretend we are in developer mode.
145 """
146 if is_enabled:
147 os.environ['MOCK_DEVELOPER_MODE'] = "1"
148 elif os.environ.get('MOCK_DEVELOPER_MODE'):
149 del os.environ['MOCK_DEVELOPER_MODE']
150
151
Ken Mixter20d9e472010-08-12 10:58:46 -0700152 def _reset_rate_limiting(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700153 """Reset the count of crash reports sent today.
154
155 This clears the contents of the rate limiting directory which has
156 the effect of reseting our count of crash reports sent.
157 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700158 utils.system('rm -rf ' + self._CRASH_SENDER_RATE_DIR)
159
160
161 def _clear_spooled_crashes(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700162 """Clears system and user crash directories.
163
164 This will remove all crash reports which are waiting to be sent.
165 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700166 utils.system('rm -rf ' + self._SYSTEM_CRASH_DIR)
Mike Frysingerded8de72013-05-29 20:45:48 -0400167 utils.system('rm -rf %s %s' % (self._USER_CRASH_DIRS,
168 self._FALLBACK_USER_CRASH_DIR))
Ken Mixter20d9e472010-08-12 10:58:46 -0700169
170
171 def _kill_running_sender(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700172 """Kill the the crash_sender process if running.
173
174 We use the PID file to find the process ID, then kill it with signal 9.
175 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700176 if not os.path.exists(self._CRASH_SENDER_RUN_PATH):
177 return
178 running_pid = int(utils.read_file(self._CRASH_SENDER_RUN_PATH))
179 logging.warning('Detected running crash sender (%d), killing' %
180 running_pid)
181 utils.system('kill -9 %d' % running_pid)
182 os.remove(self._CRASH_SENDER_RUN_PATH)
183
184
185 def _set_sending_mock(self, mock_enabled, send_success=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700186 """Enables / disables mocking of the sending process.
187
188 This uses the _MOCK_CRASH_SENDING file to achieve its aims. See notes
189 at the top.
190
191 Args:
192 mock_enabled: If True, mocking is enabled, else it is disabled.
193 send_success: If mock_enabled this is True for the mocking to
194 indicate success, False to indicate failure.
195 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700196 if mock_enabled:
197 if send_success:
198 data = ''
199 else:
200 data = '1'
201 logging.info('Setting sending mock')
202 utils.open_write_close(self._MOCK_CRASH_SENDING, data)
203 else:
204 utils.system('rm -f ' + self._MOCK_CRASH_SENDING)
205
206
207 def _set_consent(self, has_consent):
Simon Glassa47f0d72011-03-15 11:45:32 -0700208 """Sets whether or not we have consent to send crash reports.
209
210 This creates or deletes the _CONSENT_FILE to control whether
211 crash_sender will consider that it has consent to send crash reports.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200212 It also copies a policy blob with the proper policy setting.
Simon Glassa47f0d72011-03-15 11:45:32 -0700213
214 Args:
215 has_consent: True to indicate consent, False otherwise
216 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700217 if has_consent:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700218 # Create policy file that enables metrics/consent.
219 shutil.copy('/usr/local/autotest/cros/mock_metrics_on.policy',
220 self._POLICY_FILE)
221 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
222 self._OWNER_KEY_FILE)
223 # Create deprecated consent file. This is created *after* the
224 # policy file in order to avoid a race condition where chrome
225 # might remove the consent file if the policy's not set yet.
Michael Krebse9028fc2011-08-19 15:00:00 -0700226 # We create it as a temp file first in order to make the creation
227 # of the consent file, owned by chronos, atomic.
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700228 # See crosbug.com/18413.
Michael Krebse9028fc2011-08-19 15:00:00 -0700229 temp_file = self._CONSENT_FILE + '.tmp';
230 utils.open_write_close(temp_file, 'test-consent')
231 utils.system('chown chronos:chronos "%s"' % (temp_file))
232 shutil.move(temp_file, self._CONSENT_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700233 logging.info('Created ' + self._CONSENT_FILE)
234 else:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700235 # Create policy file that disables metrics/consent.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200236 shutil.copy('/usr/local/autotest/cros/mock_metrics_off.policy',
237 self._POLICY_FILE)
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700238 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
239 self._OWNER_KEY_FILE)
240 # Remove deprecated consent file.
241 utils.system('rm -f "%s"' % (self._CONSENT_FILE))
Ken Mixter20d9e472010-08-12 10:58:46 -0700242
243
Thieu Lec16253b2011-03-03 11:13:54 -0800244 def _set_crash_test_in_progress(self, in_progress):
245 if in_progress:
246 utils.open_write_close(self._CRASH_TEST_IN_PROGRESS, 'in-progress')
247 logging.info('Created ' + self._CRASH_TEST_IN_PROGRESS)
248 else:
249 utils.system('rm -f "%s"' % (self._CRASH_TEST_IN_PROGRESS))
250
251
Ken Mixter20d9e472010-08-12 10:58:46 -0700252 def _get_pushed_consent_file_path(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700253 """Returns filename of the pushed consent file."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700254 return os.path.join(self.bindir, 'pushed_consent')
255
256
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200257 def _get_pushed_policy_file_path(self):
258 """Returns filename of the pushed policy file."""
259 return os.path.join(self.bindir, 'pushed_policy')
260
261
262 def _get_pushed_owner_key_file_path(self):
263 """Returns filename of the pushed owner.key file."""
264 return os.path.join(self.bindir, 'pushed_owner_key')
265
266
Ken Mixter20d9e472010-08-12 10:58:46 -0700267 def _push_consent(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700268 """Push the consent file, thus disabling consent.
269
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200270 The consent files can be created in the new test if required. Call
Simon Glassa47f0d72011-03-15 11:45:32 -0700271 _pop_consent() to restore the original state.
272 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700273 if os.path.exists(self._CONSENT_FILE):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800274 shutil.move(self._CONSENT_FILE,
275 self._get_pushed_consent_file_path())
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200276 if os.path.exists(self._POLICY_FILE):
277 shutil.move(self._POLICY_FILE,
278 self._get_pushed_policy_file_path())
279 if os.path.exists(self._OWNER_KEY_FILE):
280 shutil.move(self._OWNER_KEY_FILE,
281 self._get_pushed_owner_key_file_path())
Ken Mixter20d9e472010-08-12 10:58:46 -0700282
283
284 def _pop_consent(self):
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200285 """Pop the consent files, enabling/disabling consent as it was before
Simon Glassa47f0d72011-03-15 11:45:32 -0700286 we pushed the consent."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700287 if os.path.exists(self._get_pushed_consent_file_path()):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800288 shutil.move(self._get_pushed_consent_file_path(),
289 self._CONSENT_FILE)
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200290 else:
291 utils.system('rm -f "%s"' % self._CONSENT_FILE)
292 if os.path.exists(self._get_pushed_policy_file_path()):
293 shutil.move(self._get_pushed_policy_file_path(),
294 self._POLICY_FILE)
295 else:
296 utils.system('rm -f "%s"' % self._POLICY_FILE)
297 if os.path.exists(self._get_pushed_owner_key_file_path()):
298 shutil.move(self._get_pushed_owner_key_file_path(),
299 self._OWNER_KEY_FILE)
300 else:
301 utils.system('rm -f "%s"' % self._OWNER_KEY_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700302
303
304 def _get_crash_dir(self, username):
Simon Glassa47f0d72011-03-15 11:45:32 -0700305 """Returns full path to the crash directory for a given username
306
Mike Frysingerded8de72013-05-29 20:45:48 -0400307 This only really works (currently) when no one is logged in. That
308 is OK (currently) as the only test that uses this runs when no one
309 is actually logged in.
310
Simon Glassa47f0d72011-03-15 11:45:32 -0700311 Args:
312 username: username to use:
313 'chronos': Returns user crash directory.
314 'root': Returns system crash directory.
315 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700316 if username == 'chronos':
Mike Frysingerded8de72013-05-29 20:45:48 -0400317 return self._FALLBACK_USER_CRASH_DIR
Ken Mixter20d9e472010-08-12 10:58:46 -0700318 else:
319 return self._SYSTEM_CRASH_DIR
320
321
322 def _initialize_crash_reporter(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700323 """Start up the crash reporter."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700324 utils.system('%s --init --nounclean_check' % self._CRASH_REPORTER_PATH)
Ken Mixterddcd92d2010-11-01 19:07:08 -0700325 # Completely disable crash_reporter from generating crash dumps
326 # while any tests are running, otherwise a crashy system can make
327 # these tests flaky.
328 self.enable_crash_filtering('none')
Ken Mixter20d9e472010-08-12 10:58:46 -0700329
330
Mike Frysingerbb54bc82014-05-14 14:04:56 -0400331 def get_crash_dir_name(self, name):
332 """Return the full path for |name| inside the system crash directory."""
333 return os.path.join(self._SYSTEM_CRASH_DIR, name)
334
335
Ken Mixter67ff5622010-09-30 15:32:17 -0700336 def write_crash_dir_entry(self, name, contents):
Simon Glassa47f0d72011-03-15 11:45:32 -0700337 """Writes an empty file to the system crash directory.
338
339 This writes a file to _SYSTEM_CRASH_DIR with the given name. This is
340 used to insert new crash dump files for testing purposes.
341
342 Args:
343 name: Name of file to write.
344 contents: String to write to the file.
345 """
Mike Frysingerbb54bc82014-05-14 14:04:56 -0400346 entry = self.get_crash_dir_name(name)
Ken Mixter20d9e472010-08-12 10:58:46 -0700347 if not os.path.exists(self._SYSTEM_CRASH_DIR):
348 os.makedirs(self._SYSTEM_CRASH_DIR)
Ken Mixter67ff5622010-09-30 15:32:17 -0700349 utils.open_write_close(entry, contents)
Ken Mixter20d9e472010-08-12 10:58:46 -0700350 return entry
351
352
Ken Mixterdee4e292010-12-14 17:45:21 -0800353 def write_fake_meta(self, name, exec_name, payload, log=None,
354 complete=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700355 """Writes a fake meta entry to the system crash directory.
356
357 Args:
358 name: Name of file to write.
359 exec_name: Value for exec_name item.
360 payload: Value for payload item.
361 log: Value for log item.
362 complete: True to close off the record, otherwise leave it
363 incomplete.
364 """
Ken Mixter1a894e02010-10-28 15:42:52 -0700365 last_line = ''
366 if complete:
367 last_line = 'done=1\n'
Ken Mixterdee4e292010-12-14 17:45:21 -0800368 contents = ('exec_name=%s\n'
369 'ver=my_ver\n'
370 'payload=%s\n'
371 '%s' % (exec_name, payload,
372 last_line))
373 if log:
374 contents = ('log=%s\n' % log) + contents
375 return self.write_crash_dir_entry(name, contents)
Ken Mixter67ff5622010-09-30 15:32:17 -0700376
377
Ken Mixter20d9e472010-08-12 10:58:46 -0700378 def _prepare_sender_one_crash(self,
379 send_success,
380 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700381 report):
Simon Glassa47f0d72011-03-15 11:45:32 -0700382 """Create metadata for a fake crash report.
383
384 This enabled mocking of the crash sender, then creates a fake
385 crash report for testing purposes.
386
387 Args:
388 send_success: True to make the crash_sender success, False to make
389 it fail.
390 reports_enabled: True to enable consent to that reports will be
391 sent.
392 report: Report to use for crash, if None we create one.
393 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700394 self._set_sending_mock(mock_enabled=True, send_success=send_success)
395 self._set_consent(reports_enabled)
Ken Mixter38dfe852010-08-18 15:24:00 -0700396 if report is None:
Mike Frysingerbb54bc82014-05-14 14:04:56 -0400397 # Use the same file format as crash does normally:
398 # <basename>.#.#.#.meta
399 payload = self.write_crash_dir_entry(
400 '%s.dmp' % self._FAKE_TEST_BASENAME, '')
401 report = self.write_fake_meta(
402 '%s.meta' % self._FAKE_TEST_BASENAME, 'fake', payload)
Ken Mixter38dfe852010-08-18 15:24:00 -0700403 return report
Ken Mixter20d9e472010-08-12 10:58:46 -0700404
405
406 def _parse_sender_output(self, output):
407 """Parse the log output from the crash_sender script.
408
409 This script can run on the logs from either a mocked or true
410 crash send.
411
412 Args:
413 output: output from the script
414
415 Returns:
416 A dictionary with these values:
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700417 error_type: an error type, if given
Ken Mixter38dfe852010-08-18 15:24:00 -0700418 exec_name: name of executable which crashed
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700419 image_type: type of image ("dev","force-official",...), if given
Michael Krebsfb875d02012-09-13 16:49:50 -0700420 boot_mode: current boot mode ("dev",...), if given
Ken Mixter67ff5622010-09-30 15:32:17 -0700421 meta_path: path to the report metadata file
422 output: the output from the script, copied
Ken Mixter38dfe852010-08-18 15:24:00 -0700423 report_kind: kind of report sent (minidump vs kernel)
Ken Mixter20d9e472010-08-12 10:58:46 -0700424 send_attempt: did the script attempt to send a crash.
425 send_success: if it attempted, was the crash send successful.
Ken Mixterd79140e2010-10-26 14:45:30 -0700426 sig: signature of the report, if given.
Ken Mixter20d9e472010-08-12 10:58:46 -0700427 sleep_time: if it attempted, how long did it sleep before
428 sending (if mocked, how long would it have slept)
Ken Mixter20d9e472010-08-12 10:58:46 -0700429 """
430 sleep_match = re.search('Scheduled to send in (\d+)s', output)
431 send_attempt = sleep_match is not None
432 if send_attempt:
433 sleep_time = int(sleep_match.group(1))
434 else:
435 sleep_time = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700436
Ken Mixter67ff5622010-09-30 15:32:17 -0700437 meta_match = re.search('Metadata: (\S+) \((\S+)\)', output)
438 if meta_match:
439 meta_path = meta_match.group(1)
440 report_kind = meta_match.group(2)
Ken Mixter38dfe852010-08-18 15:24:00 -0700441 else:
Ken Mixter67ff5622010-09-30 15:32:17 -0700442 meta_path = None
Ken Mixter38dfe852010-08-18 15:24:00 -0700443 report_kind = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700444
Ken Mixter67ff5622010-09-30 15:32:17 -0700445 payload_match = re.search('Payload: (\S+)', output)
446 if payload_match:
447 report_payload = payload_match.group(1)
448 else:
449 report_payload = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700450
Ken Mixter38dfe852010-08-18 15:24:00 -0700451 exec_name_match = re.search('Exec name: (\S+)', output)
452 if exec_name_match:
453 exec_name = exec_name_match.group(1)
454 else:
455 exec_name = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700456
Ken Mixter10c48672010-11-01 13:37:08 -0700457 sig_match = re.search('sig: (\S+)', output)
Ken Mixterd79140e2010-10-26 14:45:30 -0700458 if sig_match:
459 sig = sig_match.group(1)
460 else:
461 sig = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700462
463 error_type_match = re.search('Error type: (\S+)', output)
464 if error_type_match:
465 error_type = error_type_match.group(1)
466 else:
467 error_type = None
468
469 image_type_match = re.search('Image type: (\S+)', output)
470 if image_type_match:
471 image_type = image_type_match.group(1)
472 else:
473 image_type = None
474
Michael Krebsfb875d02012-09-13 16:49:50 -0700475 boot_mode_match = re.search('Boot mode: (\S+)', output)
476 if boot_mode_match:
477 boot_mode = boot_mode_match.group(1)
478 else:
479 boot_mode = None
480
Ken Mixter20d9e472010-08-12 10:58:46 -0700481 send_success = 'Mocking successful send' in output
Ken Mixter38dfe852010-08-18 15:24:00 -0700482 return {'exec_name': exec_name,
483 'report_kind': report_kind,
Ken Mixter67ff5622010-09-30 15:32:17 -0700484 'meta_path': meta_path,
485 'report_payload': report_payload,
Ken Mixter38dfe852010-08-18 15:24:00 -0700486 'send_attempt': send_attempt,
Ken Mixter20d9e472010-08-12 10:58:46 -0700487 'send_success': send_success,
Ken Mixterd79140e2010-10-26 14:45:30 -0700488 'sig': sig,
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700489 'error_type': error_type,
490 'image_type': image_type,
Michael Krebsfb875d02012-09-13 16:49:50 -0700491 'boot_mode': boot_mode,
Ken Mixter20d9e472010-08-12 10:58:46 -0700492 'sleep_time': sleep_time,
493 'output': output}
494
495
Ken Mixter654f32e2010-10-20 11:47:31 -0700496 def wait_for_sender_completion(self):
497 """Wait for crash_sender to complete.
498
499 Wait for no crash_sender's last message to be placed in the
500 system log before continuing and for the process to finish.
501 Otherwise we might get only part of the output."""
Eric Lie7c4cab2011-01-05 14:39:19 -0800502 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700503 lambda: self._log_reader.can_find('crash_sender done.'),
504 timeout=60,
505 exception=error.TestError(
506 'Timeout waiting for crash_sender to emit done: ' +
507 self._log_reader.get_logs()))
Eric Lie7c4cab2011-01-05 14:39:19 -0800508 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700509 lambda: utils.system('pgrep crash_sender',
510 ignore_status=True) != 0,
511 timeout=60,
512 exception=error.TestError(
513 'Timeout waiting for crash_sender to finish: ' +
514 self._log_reader.get_logs()))
515
516
Ken Mixter20d9e472010-08-12 10:58:46 -0700517 def _call_sender_one_crash(self,
518 send_success=True,
519 reports_enabled=True,
520 username='root',
Ken Mixter38dfe852010-08-18 15:24:00 -0700521 report=None):
Ken Mixter20d9e472010-08-12 10:58:46 -0700522 """Call the crash sender script to mock upload one crash.
523
524 Args:
525 send_success: Mock a successful send if true
526 reports_enabled: Has the user consented to sending crash reports.
527 username: user to emulate a crash from
Ken Mixter38dfe852010-08-18 15:24:00 -0700528 report: report to use for crash, if None we create one.
Ken Mixter20d9e472010-08-12 10:58:46 -0700529
530 Returns:
531 Returns a dictionary describing the result with the keys
532 from _parse_sender_output, as well as:
Ken Mixter38dfe852010-08-18 15:24:00 -0700533 report_exists: does the minidump still exist after calling
Ken Mixter20d9e472010-08-12 10:58:46 -0700534 send script
535 rate_count: how many crashes have been uploaded in the past
536 24 hours.
537 """
Ken Mixter38dfe852010-08-18 15:24:00 -0700538 report = self._prepare_sender_one_crash(send_success,
539 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700540 report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700541 self._log_reader.set_start_by_current()
542 script_output = utils.system_output(
543 '/bin/sh -c "%s" 2>&1' % self._CRASH_SENDER_PATH,
544 ignore_status=True)
Ken Mixter654f32e2010-10-20 11:47:31 -0700545 self.wait_for_sender_completion()
Ken Mixter20d9e472010-08-12 10:58:46 -0700546 output = self._log_reader.get_logs()
547 logging.debug('Crash sender message output:\n' + output)
548 if script_output != '':
549 raise error.TestFail(
550 'Unexpected crash_sender stdout/stderr: ' + script_output)
551
Ken Mixter38dfe852010-08-18 15:24:00 -0700552 if os.path.exists(report):
553 report_exists = True
554 os.remove(report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700555 else:
Ken Mixter38dfe852010-08-18 15:24:00 -0700556 report_exists = False
Ken Mixter20d9e472010-08-12 10:58:46 -0700557 if os.path.exists(self._CRASH_SENDER_RATE_DIR):
558 rate_count = len(os.listdir(self._CRASH_SENDER_RATE_DIR))
559 else:
560 rate_count = 0
561
562 result = self._parse_sender_output(output)
Ken Mixter38dfe852010-08-18 15:24:00 -0700563 result['report_exists'] = report_exists
Ken Mixter20d9e472010-08-12 10:58:46 -0700564 result['rate_count'] = rate_count
565
566 # Show the result for debugging but remove 'output' key
567 # since it's large and earlier in debug output.
568 debug_result = dict(result)
569 del debug_result['output']
570 logging.debug('Result of send (besides output): %s' % debug_result)
571
572 return result
573
574
Ken Mixterddcd92d2010-11-01 19:07:08 -0700575 def _replace_crash_reporter_filter_in(self, new_parameter):
Simon Glassa47f0d72011-03-15 11:45:32 -0700576 """Replaces the --filter_in= parameter of the crash reporter.
577
578 The kernel is set up to call the crash reporter with the core dump
579 as stdin when a process dies. This function adds a filter to the
580 command line used to call the crash reporter. This is used to ignore
581 crashes in which we have no interest.
582
583 This removes any --filter_in= parameter and optionally replaces it
584 with a new one.
585
586 Args:
587 new_parameter: This is parameter to add to the command line
588 instead of the --filter_in=... that was there.
589 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700590 core_pattern = utils.read_file(self._CORE_PATTERN)[:-1]
591 core_pattern = re.sub('--filter_in=\S*\s*', '',
592 core_pattern).rstrip()
593 if new_parameter:
594 core_pattern += ' ' + new_parameter
595 utils.system('echo "%s" > %s' % (core_pattern, self._CORE_PATTERN))
596
597
598 def enable_crash_filtering(self, name):
Simon Glassa47f0d72011-03-15 11:45:32 -0700599 """Add a --filter_in argument to the kernel core dump cmdline.
600
601 Args:
602 name: Filter text to use. This is passed as a --filter_in
603 argument to the crash reporter.
604 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700605 self._replace_crash_reporter_filter_in('--filter_in=' + name)
606
607
608 def disable_crash_filtering(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700609 """Remove the --filter_in argument from the kernel core dump cmdline.
610
611 Next time the crash reporter is invoked (due to a crash) it will not
612 receive a --filter_in paramter."""
Ken Mixterddcd92d2010-11-01 19:07:08 -0700613 self._replace_crash_reporter_filter_in('')
614
615
Mike Frysinger0fa79ab2014-05-24 21:16:04 -0400616 @contextlib.contextmanager
617 def hold_crash_lock(self):
618 """A context manager to hold the crash sender lock."""
619 with open(self._CRASH_SENDER_LOCK_PATH, 'w+') as f:
620 fcntl.flock(f.fileno(), fcntl.LOCK_EX)
621 try:
622 yield
623 finally:
624 fcntl.flock(f.fileno(), fcntl.LOCK_UN)
625
626
Ken Mixter20d9e472010-08-12 10:58:46 -0700627 def initialize(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700628 """Initalize the test."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700629 test.test.initialize(self)
Eric Lie7c4cab2011-01-05 14:39:19 -0800630 self._log_reader = cros_logging.LogReader()
Ken Mixter38dfe852010-08-18 15:24:00 -0700631 self._leave_crash_sending = True
Ken Mixter67ff5622010-09-30 15:32:17 -0700632 self._automatic_consent_saving = True
Ken Mixterddcd92d2010-11-01 19:07:08 -0700633 self.enable_crash_filtering('none')
Thieu Lec16253b2011-03-03 11:13:54 -0800634 self._set_crash_test_in_progress(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700635
636
637 def cleanup(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700638 """Cleanup after the test.
639
640 We reset things back to the way we think they should be. This is
641 intended to allow the system to continue normal operation.
642
643 Some variables silently change the behavior:
644 _automatic_consent_saving: if True, we pop the consent file.
645 _leave_crash_sending: True to enable crash sending, False to
646 disable it
647 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700648 self._reset_rate_limiting()
649 self._clear_spooled_crashes()
Ken Mixter4f619652010-10-18 12:11:18 -0700650 self._set_system_sending(self._leave_crash_sending)
Ken Mixter20d9e472010-08-12 10:58:46 -0700651 self._set_sending_mock(mock_enabled=False)
Ken Mixter67ff5622010-09-30 15:32:17 -0700652 if self._automatic_consent_saving:
653 self._pop_consent()
Ken Mixterddcd92d2010-11-01 19:07:08 -0700654 self.disable_crash_filtering()
Thieu Lec16253b2011-03-03 11:13:54 -0800655 self._set_crash_test_in_progress(False)
Ken Mixter20d9e472010-08-12 10:58:46 -0700656 test.test.cleanup(self)
657
658
Ken Mixter38dfe852010-08-18 15:24:00 -0700659 def run_crash_tests(self,
660 test_names,
661 initialize_crash_reporter=False,
662 clear_spool_first=True,
663 must_run_all=True):
664 """Run crash tests defined in this class.
665
666 Args:
Simon Glassa47f0d72011-03-15 11:45:32 -0700667 test_names: Array of test names.
668 initialize_crash_reporter: Should set up crash reporter for every
669 run.
670 clear_spool_first: Clear all spooled user/system crashes before
671 starting the test.
672 must_run_all: Should make sure every test in this class is
673 mentioned in test_names.
Ken Mixter38dfe852010-08-18 15:24:00 -0700674 """
Ken Mixter67ff5622010-09-30 15:32:17 -0700675 if self._automatic_consent_saving:
676 self._push_consent()
Ken Mixter20d9e472010-08-12 10:58:46 -0700677
Ken Mixter38dfe852010-08-18 15:24:00 -0700678 if must_run_all:
679 # Sanity check test_names is complete
680 for attr in dir(self):
681 if attr.find('_test_') == 0:
682 test_name = attr[6:]
683 if not test_name in test_names:
684 raise error.TestError('Test %s is missing' % test_name)
Ken Mixter20d9e472010-08-12 10:58:46 -0700685
686 for test_name in test_names:
687 logging.info(('=' * 20) + ('Running %s' % test_name) + ('=' * 20))
Ken Mixter38dfe852010-08-18 15:24:00 -0700688 if initialize_crash_reporter:
689 self._initialize_crash_reporter()
Ken Mixter4f619652010-10-18 12:11:18 -0700690 # Disable crash_sender from running, kill off any running ones, but
691 # set environment so crash_sender may run as a child process.
692 self._set_system_sending(False)
693 self._set_child_sending(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700694 self._kill_running_sender()
695 self._reset_rate_limiting()
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700696 # Default to not overriding for unofficial versions.
697 self._set_force_official(False)
Michael Krebsfb875d02012-09-13 16:49:50 -0700698 # Default to not pretending we're in developer mode.
699 self._set_mock_developer_mode(False)
Ken Mixter38dfe852010-08-18 15:24:00 -0700700 if clear_spool_first:
701 self._clear_spooled_crashes()
Simon Glassa47f0d72011-03-15 11:45:32 -0700702
703 # Call the test function
Ken Mixter20d9e472010-08-12 10:58:46 -0700704 getattr(self, '_test_' + test_name)()