blob: c4aa1d6c47126ac8c9c39356b94077428e0f3b16 [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
Bertrand SIMONNET9347d362014-06-30 11:17:59 -07007import common, constants, 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'
Ken Mixterddcd92d2010-11-01 19:07:08 -070070 _CORE_PATTERN = '/proc/sys/kernel/core_pattern'
Ken Mixter20d9e472010-08-12 10:58:46 -070071 _CRASH_REPORTER_PATH = '/sbin/crash_reporter'
72 _CRASH_SENDER_PATH = '/sbin/crash_sender'
73 _CRASH_SENDER_RATE_DIR = '/var/lib/crash_sender'
74 _CRASH_SENDER_RUN_PATH = '/var/run/crash_sender.pid'
Mike Frysinger0fa79ab2014-05-24 21:16:04 -040075 _CRASH_SENDER_LOCK_PATH = '/var/lock/crash_sender'
Thieu Lec16253b2011-03-03 11:13:54 -080076 _CRASH_TEST_IN_PROGRESS = '/tmp/crash-test-in-progress'
Ken Mixter20d9e472010-08-12 10:58:46 -070077 _MOCK_CRASH_SENDING = '/tmp/mock-crash-sending'
Ken Mixter38dfe852010-08-18 15:24:00 -070078 _PAUSE_FILE = '/var/lib/crash_sender_paused'
Ken Mixter20d9e472010-08-12 10:58:46 -070079 _SYSTEM_CRASH_DIR = '/var/spool/crash'
Mike Frysingerded8de72013-05-29 20:45:48 -040080 _FALLBACK_USER_CRASH_DIR = '/home/chronos/crash'
81 _USER_CRASH_DIRS = '/home/chronos/u-*/crash'
Ken Mixter20d9e472010-08-12 10:58:46 -070082
Mike Frysingerbb54bc82014-05-14 14:04:56 -040083 # Use the same file format as crash does normally:
84 # <basename>.#.#.#.meta
85 _FAKE_TEST_BASENAME = 'fake.1.2.3'
86
Ken Mixter4f619652010-10-18 12:11:18 -070087 def _set_system_sending(self, is_enabled):
88 """Sets whether or not the system crash_sender is allowed to run.
89
Simon Glassa47f0d72011-03-15 11:45:32 -070090 This is done by creating or removing _PAUSE_FILE.
91
Ken Mixter4f619652010-10-18 12:11:18 -070092 crash_sender may still be allowed to run if _set_child_sending is
Simon Glassa47f0d72011-03-15 11:45:32 -070093 called with True and it is run as a child process.
94
95 Args:
96 is_enabled: True to enable crash_sender, False to disable it.
97 """
Ken Mixter20d9e472010-08-12 10:58:46 -070098 if is_enabled:
99 if os.path.exists(self._PAUSE_FILE):
100 os.remove(self._PAUSE_FILE)
101 else:
102 utils.system('touch ' + self._PAUSE_FILE)
103
104
Ken Mixter4f619652010-10-18 12:11:18 -0700105 def _set_child_sending(self, is_enabled):
Simon Glassa47f0d72011-03-15 11:45:32 -0700106 """Overrides crash sending enabling for child processes.
107
108 When the system crash sender is disabled this test can manually run
109 the crash sender as a child process. Normally this would do nothing,
110 but this function sets up crash_sender to ignore its disabled status
111 and do its job.
112
113 Args:
114 is_enabled: True to enable crash sending for child processes.
115 """
Ken Mixter4f619652010-10-18 12:11:18 -0700116 if is_enabled:
117 os.environ['OVERRIDE_PAUSE_SENDING'] = "1"
118 else:
119 del os.environ['OVERRIDE_PAUSE_SENDING']
120
121
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700122 def _set_force_official(self, is_enabled):
123 """Sets whether or not reports will upload for unofficial versions.
124
125 Normally, crash reports are only uploaded for official build
126 versions. If the override is set, however, they will also be
127 uploaded for unofficial versions.
128
129 Args:
130 is_enabled: True to enable uploading for unofficial versions.
131 """
132 if is_enabled:
133 os.environ['FORCE_OFFICIAL'] = "1"
134 elif os.environ.get('FORCE_OFFICIAL'):
135 del os.environ['FORCE_OFFICIAL']
136
137
Michael Krebsfb875d02012-09-13 16:49:50 -0700138 def _set_mock_developer_mode(self, is_enabled):
139 """Sets whether or not we should pretend we booted in developer mode.
140
141 Args:
142 is_enabled: True to pretend we are in developer mode.
143 """
144 if is_enabled:
145 os.environ['MOCK_DEVELOPER_MODE'] = "1"
146 elif os.environ.get('MOCK_DEVELOPER_MODE'):
147 del os.environ['MOCK_DEVELOPER_MODE']
148
149
Ken Mixter20d9e472010-08-12 10:58:46 -0700150 def _reset_rate_limiting(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700151 """Reset the count of crash reports sent today.
152
153 This clears the contents of the rate limiting directory which has
154 the effect of reseting our count of crash reports sent.
155 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700156 utils.system('rm -rf ' + self._CRASH_SENDER_RATE_DIR)
157
158
159 def _clear_spooled_crashes(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700160 """Clears system and user crash directories.
161
162 This will remove all crash reports which are waiting to be sent.
163 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700164 utils.system('rm -rf ' + self._SYSTEM_CRASH_DIR)
Mike Frysingerded8de72013-05-29 20:45:48 -0400165 utils.system('rm -rf %s %s' % (self._USER_CRASH_DIRS,
166 self._FALLBACK_USER_CRASH_DIR))
Ken Mixter20d9e472010-08-12 10:58:46 -0700167
168
169 def _kill_running_sender(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700170 """Kill the the crash_sender process if running.
171
172 We use the PID file to find the process ID, then kill it with signal 9.
173 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700174 if not os.path.exists(self._CRASH_SENDER_RUN_PATH):
175 return
176 running_pid = int(utils.read_file(self._CRASH_SENDER_RUN_PATH))
177 logging.warning('Detected running crash sender (%d), killing' %
178 running_pid)
179 utils.system('kill -9 %d' % running_pid)
180 os.remove(self._CRASH_SENDER_RUN_PATH)
181
182
183 def _set_sending_mock(self, mock_enabled, send_success=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700184 """Enables / disables mocking of the sending process.
185
186 This uses the _MOCK_CRASH_SENDING file to achieve its aims. See notes
187 at the top.
188
189 Args:
190 mock_enabled: If True, mocking is enabled, else it is disabled.
191 send_success: If mock_enabled this is True for the mocking to
192 indicate success, False to indicate failure.
193 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700194 if mock_enabled:
195 if send_success:
196 data = ''
197 else:
198 data = '1'
199 logging.info('Setting sending mock')
200 utils.open_write_close(self._MOCK_CRASH_SENDING, data)
201 else:
202 utils.system('rm -f ' + self._MOCK_CRASH_SENDING)
203
204
205 def _set_consent(self, has_consent):
Simon Glassa47f0d72011-03-15 11:45:32 -0700206 """Sets whether or not we have consent to send crash reports.
207
208 This creates or deletes the _CONSENT_FILE to control whether
209 crash_sender will consider that it has consent to send crash reports.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200210 It also copies a policy blob with the proper policy setting.
Simon Glassa47f0d72011-03-15 11:45:32 -0700211
212 Args:
213 has_consent: True to indicate consent, False otherwise
214 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700215 if has_consent:
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700216 if os.path.isdir(constants.WHITELIST_DIR):
217 # Create policy file that enables metrics/consent.
218 shutil.copy('/usr/local/autotest/cros/mock_metrics_on.policy',
219 constants.SIGNED_POLICY_FILE)
220 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
221 constants.OWNER_KEY_FILE)
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700222 # 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:
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700234 if os.path.isdir(constants.WHITELIST_DIR):
235 # Create policy file that disables metrics/consent.
236 shutil.copy('/usr/local/autotest/cros/mock_metrics_off.policy',
237 constants.SIGNED_POLICY_FILE)
238 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
239 constants.OWNER_KEY_FILE)
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700240 # 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())
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700276 if os.path.exists(constants.SIGNED_POLICY_FILE):
277 shutil.move(constants.SIGNED_POLICY_FILE,
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200278 self._get_pushed_policy_file_path())
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700279 if os.path.exists(constants.OWNER_KEY_FILE):
280 shutil.move(constants.OWNER_KEY_FILE,
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200281 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(),
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700294 constants.SIGNED_POLICY_FILE)
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200295 else:
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700296 utils.system('rm -f "%s"' % constants.SIGNED_POLICY_FILE)
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200297 if os.path.exists(self._get_pushed_owner_key_file_path()):
298 shutil.move(self._get_pushed_owner_key_file_path(),
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700299 constants.OWNER_KEY_FILE)
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200300 else:
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700301 utils.system('rm -f "%s"' % constants.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',
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700521 report=None,
522 should_fail=False):
Ken Mixter20d9e472010-08-12 10:58:46 -0700523 """Call the crash sender script to mock upload one crash.
524
525 Args:
526 send_success: Mock a successful send if true
527 reports_enabled: Has the user consented to sending crash reports.
528 username: user to emulate a crash from
Ken Mixter38dfe852010-08-18 15:24:00 -0700529 report: report to use for crash, if None we create one.
Ken Mixter20d9e472010-08-12 10:58:46 -0700530
531 Returns:
532 Returns a dictionary describing the result with the keys
533 from _parse_sender_output, as well as:
Ken Mixter38dfe852010-08-18 15:24:00 -0700534 report_exists: does the minidump still exist after calling
Ken Mixter20d9e472010-08-12 10:58:46 -0700535 send script
536 rate_count: how many crashes have been uploaded in the past
537 24 hours.
538 """
Ken Mixter38dfe852010-08-18 15:24:00 -0700539 report = self._prepare_sender_one_crash(send_success,
540 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700541 report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700542 self._log_reader.set_start_by_current()
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700543 script_output = ""
544 try:
545 script_output = utils.system_output(
546 '/bin/sh -c "%s" 2>&1' % self._CRASH_SENDER_PATH,
547 ignore_status=should_fail)
548 except error.CmdError as err:
549 raise error.TestFail('"%s" returned an unexpected non-zero '
550 'value (%s).'
551 % (err.command, err.result_obj.exit_status))
552
Ken Mixter654f32e2010-10-20 11:47:31 -0700553 self.wait_for_sender_completion()
Ken Mixter20d9e472010-08-12 10:58:46 -0700554 output = self._log_reader.get_logs()
555 logging.debug('Crash sender message output:\n' + output)
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700556
Ken Mixter20d9e472010-08-12 10:58:46 -0700557 if script_output != '':
Bertrand SIMONNET9347d362014-06-30 11:17:59 -0700558 logging.debug('crash_sender stdout/stderr: ' + script_output)
Ken Mixter20d9e472010-08-12 10:58:46 -0700559
Ken Mixter38dfe852010-08-18 15:24:00 -0700560 if os.path.exists(report):
561 report_exists = True
562 os.remove(report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700563 else:
Ken Mixter38dfe852010-08-18 15:24:00 -0700564 report_exists = False
Ken Mixter20d9e472010-08-12 10:58:46 -0700565 if os.path.exists(self._CRASH_SENDER_RATE_DIR):
566 rate_count = len(os.listdir(self._CRASH_SENDER_RATE_DIR))
567 else:
568 rate_count = 0
569
570 result = self._parse_sender_output(output)
Ken Mixter38dfe852010-08-18 15:24:00 -0700571 result['report_exists'] = report_exists
Ken Mixter20d9e472010-08-12 10:58:46 -0700572 result['rate_count'] = rate_count
573
574 # Show the result for debugging but remove 'output' key
575 # since it's large and earlier in debug output.
576 debug_result = dict(result)
577 del debug_result['output']
578 logging.debug('Result of send (besides output): %s' % debug_result)
579
580 return result
581
582
Ken Mixterddcd92d2010-11-01 19:07:08 -0700583 def _replace_crash_reporter_filter_in(self, new_parameter):
Simon Glassa47f0d72011-03-15 11:45:32 -0700584 """Replaces the --filter_in= parameter of the crash reporter.
585
586 The kernel is set up to call the crash reporter with the core dump
587 as stdin when a process dies. This function adds a filter to the
588 command line used to call the crash reporter. This is used to ignore
589 crashes in which we have no interest.
590
591 This removes any --filter_in= parameter and optionally replaces it
592 with a new one.
593
594 Args:
595 new_parameter: This is parameter to add to the command line
596 instead of the --filter_in=... that was there.
597 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700598 core_pattern = utils.read_file(self._CORE_PATTERN)[:-1]
599 core_pattern = re.sub('--filter_in=\S*\s*', '',
600 core_pattern).rstrip()
601 if new_parameter:
602 core_pattern += ' ' + new_parameter
603 utils.system('echo "%s" > %s' % (core_pattern, self._CORE_PATTERN))
604
605
606 def enable_crash_filtering(self, name):
Simon Glassa47f0d72011-03-15 11:45:32 -0700607 """Add a --filter_in argument to the kernel core dump cmdline.
608
609 Args:
610 name: Filter text to use. This is passed as a --filter_in
611 argument to the crash reporter.
612 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700613 self._replace_crash_reporter_filter_in('--filter_in=' + name)
614
615
616 def disable_crash_filtering(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700617 """Remove the --filter_in argument from the kernel core dump cmdline.
618
619 Next time the crash reporter is invoked (due to a crash) it will not
620 receive a --filter_in paramter."""
Ken Mixterddcd92d2010-11-01 19:07:08 -0700621 self._replace_crash_reporter_filter_in('')
622
623
Mike Frysinger0fa79ab2014-05-24 21:16:04 -0400624 @contextlib.contextmanager
625 def hold_crash_lock(self):
626 """A context manager to hold the crash sender lock."""
627 with open(self._CRASH_SENDER_LOCK_PATH, 'w+') as f:
628 fcntl.flock(f.fileno(), fcntl.LOCK_EX)
629 try:
630 yield
631 finally:
632 fcntl.flock(f.fileno(), fcntl.LOCK_UN)
633
634
Ken Mixter20d9e472010-08-12 10:58:46 -0700635 def initialize(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700636 """Initalize the test."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700637 test.test.initialize(self)
Eric Lie7c4cab2011-01-05 14:39:19 -0800638 self._log_reader = cros_logging.LogReader()
Ken Mixter38dfe852010-08-18 15:24:00 -0700639 self._leave_crash_sending = True
Ken Mixter67ff5622010-09-30 15:32:17 -0700640 self._automatic_consent_saving = True
Ken Mixterddcd92d2010-11-01 19:07:08 -0700641 self.enable_crash_filtering('none')
Thieu Lec16253b2011-03-03 11:13:54 -0800642 self._set_crash_test_in_progress(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700643
644
645 def cleanup(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700646 """Cleanup after the test.
647
648 We reset things back to the way we think they should be. This is
649 intended to allow the system to continue normal operation.
650
651 Some variables silently change the behavior:
652 _automatic_consent_saving: if True, we pop the consent file.
653 _leave_crash_sending: True to enable crash sending, False to
654 disable it
655 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700656 self._reset_rate_limiting()
657 self._clear_spooled_crashes()
Ken Mixter4f619652010-10-18 12:11:18 -0700658 self._set_system_sending(self._leave_crash_sending)
Ken Mixter20d9e472010-08-12 10:58:46 -0700659 self._set_sending_mock(mock_enabled=False)
Ken Mixter67ff5622010-09-30 15:32:17 -0700660 if self._automatic_consent_saving:
661 self._pop_consent()
Ken Mixterddcd92d2010-11-01 19:07:08 -0700662 self.disable_crash_filtering()
Thieu Lec16253b2011-03-03 11:13:54 -0800663 self._set_crash_test_in_progress(False)
Ken Mixter20d9e472010-08-12 10:58:46 -0700664 test.test.cleanup(self)
665
666
Ken Mixter38dfe852010-08-18 15:24:00 -0700667 def run_crash_tests(self,
668 test_names,
669 initialize_crash_reporter=False,
670 clear_spool_first=True,
671 must_run_all=True):
672 """Run crash tests defined in this class.
673
674 Args:
Simon Glassa47f0d72011-03-15 11:45:32 -0700675 test_names: Array of test names.
676 initialize_crash_reporter: Should set up crash reporter for every
677 run.
678 clear_spool_first: Clear all spooled user/system crashes before
679 starting the test.
680 must_run_all: Should make sure every test in this class is
681 mentioned in test_names.
Ken Mixter38dfe852010-08-18 15:24:00 -0700682 """
Ken Mixter67ff5622010-09-30 15:32:17 -0700683 if self._automatic_consent_saving:
684 self._push_consent()
Ken Mixter20d9e472010-08-12 10:58:46 -0700685
Ken Mixter38dfe852010-08-18 15:24:00 -0700686 if must_run_all:
687 # Sanity check test_names is complete
688 for attr in dir(self):
689 if attr.find('_test_') == 0:
690 test_name = attr[6:]
691 if not test_name in test_names:
692 raise error.TestError('Test %s is missing' % test_name)
Ken Mixter20d9e472010-08-12 10:58:46 -0700693
694 for test_name in test_names:
695 logging.info(('=' * 20) + ('Running %s' % test_name) + ('=' * 20))
Ken Mixter38dfe852010-08-18 15:24:00 -0700696 if initialize_crash_reporter:
697 self._initialize_crash_reporter()
Ken Mixter4f619652010-10-18 12:11:18 -0700698 # Disable crash_sender from running, kill off any running ones, but
699 # set environment so crash_sender may run as a child process.
700 self._set_system_sending(False)
701 self._set_child_sending(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700702 self._kill_running_sender()
703 self._reset_rate_limiting()
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700704 # Default to not overriding for unofficial versions.
705 self._set_force_official(False)
Michael Krebsfb875d02012-09-13 16:49:50 -0700706 # Default to not pretending we're in developer mode.
707 self._set_mock_developer_mode(False)
Ken Mixter38dfe852010-08-18 15:24:00 -0700708 if clear_spool_first:
709 self._clear_spooled_crashes()
Simon Glassa47f0d72011-03-15 11:45:32 -0700710
711 # Call the test function
Ken Mixter20d9e472010-08-12 10:58:46 -0700712 getattr(self, '_test_' + test_name)()