blob: 25fdbf08289154c2b0c2e5aecc74eef9019e949a [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'
81 _USER_CRASH_DIR = '/home/chronos/user/crash'
82
Ken Mixter4f619652010-10-18 12:11:18 -070083 def _set_system_sending(self, is_enabled):
84 """Sets whether or not the system crash_sender is allowed to run.
85
Simon Glassa47f0d72011-03-15 11:45:32 -070086 This is done by creating or removing _PAUSE_FILE.
87
Ken Mixter4f619652010-10-18 12:11:18 -070088 crash_sender may still be allowed to run if _set_child_sending is
Simon Glassa47f0d72011-03-15 11:45:32 -070089 called with True and it is run as a child process.
90
91 Args:
92 is_enabled: True to enable crash_sender, False to disable it.
93 """
Ken Mixter20d9e472010-08-12 10:58:46 -070094 if is_enabled:
95 if os.path.exists(self._PAUSE_FILE):
96 os.remove(self._PAUSE_FILE)
97 else:
98 utils.system('touch ' + self._PAUSE_FILE)
99
100
Ken Mixter4f619652010-10-18 12:11:18 -0700101 def _set_child_sending(self, is_enabled):
Simon Glassa47f0d72011-03-15 11:45:32 -0700102 """Overrides crash sending enabling for child processes.
103
104 When the system crash sender is disabled this test can manually run
105 the crash sender as a child process. Normally this would do nothing,
106 but this function sets up crash_sender to ignore its disabled status
107 and do its job.
108
109 Args:
110 is_enabled: True to enable crash sending for child processes.
111 """
Ken Mixter4f619652010-10-18 12:11:18 -0700112 if is_enabled:
113 os.environ['OVERRIDE_PAUSE_SENDING'] = "1"
114 else:
115 del os.environ['OVERRIDE_PAUSE_SENDING']
116
117
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700118 def _set_force_official(self, is_enabled):
119 """Sets whether or not reports will upload for unofficial versions.
120
121 Normally, crash reports are only uploaded for official build
122 versions. If the override is set, however, they will also be
123 uploaded for unofficial versions.
124
125 Args:
126 is_enabled: True to enable uploading for unofficial versions.
127 """
128 if is_enabled:
129 os.environ['FORCE_OFFICIAL'] = "1"
130 elif os.environ.get('FORCE_OFFICIAL'):
131 del os.environ['FORCE_OFFICIAL']
132
133
Michael Krebsfb875d02012-09-13 16:49:50 -0700134 def _set_mock_developer_mode(self, is_enabled):
135 """Sets whether or not we should pretend we booted in developer mode.
136
137 Args:
138 is_enabled: True to pretend we are in developer mode.
139 """
140 if is_enabled:
141 os.environ['MOCK_DEVELOPER_MODE'] = "1"
142 elif os.environ.get('MOCK_DEVELOPER_MODE'):
143 del os.environ['MOCK_DEVELOPER_MODE']
144
145
Ken Mixter20d9e472010-08-12 10:58:46 -0700146 def _reset_rate_limiting(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700147 """Reset the count of crash reports sent today.
148
149 This clears the contents of the rate limiting directory which has
150 the effect of reseting our count of crash reports sent.
151 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700152 utils.system('rm -rf ' + self._CRASH_SENDER_RATE_DIR)
153
154
155 def _clear_spooled_crashes(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700156 """Clears system and user crash directories.
157
158 This will remove all crash reports which are waiting to be sent.
159 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700160 utils.system('rm -rf ' + self._SYSTEM_CRASH_DIR)
161 utils.system('rm -rf ' + self._USER_CRASH_DIR)
162
163
164 def _kill_running_sender(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700165 """Kill the the crash_sender process if running.
166
167 We use the PID file to find the process ID, then kill it with signal 9.
168 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700169 if not os.path.exists(self._CRASH_SENDER_RUN_PATH):
170 return
171 running_pid = int(utils.read_file(self._CRASH_SENDER_RUN_PATH))
172 logging.warning('Detected running crash sender (%d), killing' %
173 running_pid)
174 utils.system('kill -9 %d' % running_pid)
175 os.remove(self._CRASH_SENDER_RUN_PATH)
176
177
178 def _set_sending_mock(self, mock_enabled, send_success=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700179 """Enables / disables mocking of the sending process.
180
181 This uses the _MOCK_CRASH_SENDING file to achieve its aims. See notes
182 at the top.
183
184 Args:
185 mock_enabled: If True, mocking is enabled, else it is disabled.
186 send_success: If mock_enabled this is True for the mocking to
187 indicate success, False to indicate failure.
188 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700189 if mock_enabled:
190 if send_success:
191 data = ''
192 else:
193 data = '1'
194 logging.info('Setting sending mock')
195 utils.open_write_close(self._MOCK_CRASH_SENDING, data)
196 else:
197 utils.system('rm -f ' + self._MOCK_CRASH_SENDING)
198
199
200 def _set_consent(self, has_consent):
Simon Glassa47f0d72011-03-15 11:45:32 -0700201 """Sets whether or not we have consent to send crash reports.
202
203 This creates or deletes the _CONSENT_FILE to control whether
204 crash_sender will consider that it has consent to send crash reports.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200205 It also copies a policy blob with the proper policy setting.
Simon Glassa47f0d72011-03-15 11:45:32 -0700206
207 Args:
208 has_consent: True to indicate consent, False otherwise
209 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700210 if has_consent:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700211 # Create policy file that enables metrics/consent.
212 shutil.copy('/usr/local/autotest/cros/mock_metrics_on.policy',
213 self._POLICY_FILE)
214 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
215 self._OWNER_KEY_FILE)
216 # Create deprecated consent file. This is created *after* the
217 # policy file in order to avoid a race condition where chrome
218 # might remove the consent file if the policy's not set yet.
Michael Krebse9028fc2011-08-19 15:00:00 -0700219 # We create it as a temp file first in order to make the creation
220 # of the consent file, owned by chronos, atomic.
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700221 # See crosbug.com/18413.
Michael Krebse9028fc2011-08-19 15:00:00 -0700222 temp_file = self._CONSENT_FILE + '.tmp';
223 utils.open_write_close(temp_file, 'test-consent')
224 utils.system('chown chronos:chronos "%s"' % (temp_file))
225 shutil.move(temp_file, self._CONSENT_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700226 logging.info('Created ' + self._CONSENT_FILE)
227 else:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700228 # Create policy file that disables metrics/consent.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200229 shutil.copy('/usr/local/autotest/cros/mock_metrics_off.policy',
230 self._POLICY_FILE)
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700231 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
232 self._OWNER_KEY_FILE)
233 # Remove deprecated consent file.
234 utils.system('rm -f "%s"' % (self._CONSENT_FILE))
Ken Mixter20d9e472010-08-12 10:58:46 -0700235
236
Thieu Lec16253b2011-03-03 11:13:54 -0800237 def _set_crash_test_in_progress(self, in_progress):
238 if in_progress:
239 utils.open_write_close(self._CRASH_TEST_IN_PROGRESS, 'in-progress')
240 logging.info('Created ' + self._CRASH_TEST_IN_PROGRESS)
241 else:
242 utils.system('rm -f "%s"' % (self._CRASH_TEST_IN_PROGRESS))
243
244
Ken Mixter20d9e472010-08-12 10:58:46 -0700245 def _get_pushed_consent_file_path(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700246 """Returns filename of the pushed consent file."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700247 return os.path.join(self.bindir, 'pushed_consent')
248
249
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200250 def _get_pushed_policy_file_path(self):
251 """Returns filename of the pushed policy file."""
252 return os.path.join(self.bindir, 'pushed_policy')
253
254
255 def _get_pushed_owner_key_file_path(self):
256 """Returns filename of the pushed owner.key file."""
257 return os.path.join(self.bindir, 'pushed_owner_key')
258
259
Ken Mixter20d9e472010-08-12 10:58:46 -0700260 def _push_consent(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700261 """Push the consent file, thus disabling consent.
262
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200263 The consent files can be created in the new test if required. Call
Simon Glassa47f0d72011-03-15 11:45:32 -0700264 _pop_consent() to restore the original state.
265 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700266 if os.path.exists(self._CONSENT_FILE):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800267 shutil.move(self._CONSENT_FILE,
268 self._get_pushed_consent_file_path())
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200269 if os.path.exists(self._POLICY_FILE):
270 shutil.move(self._POLICY_FILE,
271 self._get_pushed_policy_file_path())
272 if os.path.exists(self._OWNER_KEY_FILE):
273 shutil.move(self._OWNER_KEY_FILE,
274 self._get_pushed_owner_key_file_path())
Ken Mixter20d9e472010-08-12 10:58:46 -0700275
276
277 def _pop_consent(self):
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200278 """Pop the consent files, enabling/disabling consent as it was before
Simon Glassa47f0d72011-03-15 11:45:32 -0700279 we pushed the consent."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700280 if os.path.exists(self._get_pushed_consent_file_path()):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800281 shutil.move(self._get_pushed_consent_file_path(),
282 self._CONSENT_FILE)
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200283 else:
284 utils.system('rm -f "%s"' % self._CONSENT_FILE)
285 if os.path.exists(self._get_pushed_policy_file_path()):
286 shutil.move(self._get_pushed_policy_file_path(),
287 self._POLICY_FILE)
288 else:
289 utils.system('rm -f "%s"' % self._POLICY_FILE)
290 if os.path.exists(self._get_pushed_owner_key_file_path()):
291 shutil.move(self._get_pushed_owner_key_file_path(),
292 self._OWNER_KEY_FILE)
293 else:
294 utils.system('rm -f "%s"' % self._OWNER_KEY_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700295
296
297 def _get_crash_dir(self, username):
Simon Glassa47f0d72011-03-15 11:45:32 -0700298 """Returns full path to the crash directory for a given username
299
300 Args:
301 username: username to use:
302 'chronos': Returns user crash directory.
303 'root': Returns system crash directory.
304 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700305 if username == 'chronos':
306 return self._USER_CRASH_DIR
307 else:
308 return self._SYSTEM_CRASH_DIR
309
310
311 def _initialize_crash_reporter(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700312 """Start up the crash reporter."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700313 utils.system('%s --init --nounclean_check' % self._CRASH_REPORTER_PATH)
Ken Mixterddcd92d2010-11-01 19:07:08 -0700314 # Completely disable crash_reporter from generating crash dumps
315 # while any tests are running, otherwise a crashy system can make
316 # these tests flaky.
317 self.enable_crash_filtering('none')
Ken Mixter20d9e472010-08-12 10:58:46 -0700318
319
Ken Mixter67ff5622010-09-30 15:32:17 -0700320 def write_crash_dir_entry(self, name, contents):
Simon Glassa47f0d72011-03-15 11:45:32 -0700321 """Writes an empty file to the system crash directory.
322
323 This writes a file to _SYSTEM_CRASH_DIR with the given name. This is
324 used to insert new crash dump files for testing purposes.
325
326 Args:
327 name: Name of file to write.
328 contents: String to write to the file.
329 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700330 entry = os.path.join(self._SYSTEM_CRASH_DIR, name)
331 if not os.path.exists(self._SYSTEM_CRASH_DIR):
332 os.makedirs(self._SYSTEM_CRASH_DIR)
Ken Mixter67ff5622010-09-30 15:32:17 -0700333 utils.open_write_close(entry, contents)
Ken Mixter20d9e472010-08-12 10:58:46 -0700334 return entry
335
336
Ken Mixterdee4e292010-12-14 17:45:21 -0800337 def write_fake_meta(self, name, exec_name, payload, log=None,
338 complete=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700339 """Writes a fake meta entry to the system crash directory.
340
341 Args:
342 name: Name of file to write.
343 exec_name: Value for exec_name item.
344 payload: Value for payload item.
345 log: Value for log item.
346 complete: True to close off the record, otherwise leave it
347 incomplete.
348 """
Ken Mixter1a894e02010-10-28 15:42:52 -0700349 last_line = ''
350 if complete:
351 last_line = 'done=1\n'
Ken Mixterdee4e292010-12-14 17:45:21 -0800352 contents = ('exec_name=%s\n'
353 'ver=my_ver\n'
354 'payload=%s\n'
355 '%s' % (exec_name, payload,
356 last_line))
357 if log:
358 contents = ('log=%s\n' % log) + contents
359 return self.write_crash_dir_entry(name, contents)
Ken Mixter67ff5622010-09-30 15:32:17 -0700360
361
Ken Mixter20d9e472010-08-12 10:58:46 -0700362 def _prepare_sender_one_crash(self,
363 send_success,
364 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700365 report):
Simon Glassa47f0d72011-03-15 11:45:32 -0700366 """Create metadata for a fake crash report.
367
368 This enabled mocking of the crash sender, then creates a fake
369 crash report for testing purposes.
370
371 Args:
372 send_success: True to make the crash_sender success, False to make
373 it fail.
374 reports_enabled: True to enable consent to that reports will be
375 sent.
376 report: Report to use for crash, if None we create one.
377 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700378 self._set_sending_mock(mock_enabled=True, send_success=send_success)
379 self._set_consent(reports_enabled)
Ken Mixter38dfe852010-08-18 15:24:00 -0700380 if report is None:
Ken Mixter1a894e02010-10-28 15:42:52 -0700381 payload = self.write_crash_dir_entry('fake.dmp', '')
382 report = self.write_fake_meta('fake.meta', 'fake', payload)
Ken Mixter38dfe852010-08-18 15:24:00 -0700383 return report
Ken Mixter20d9e472010-08-12 10:58:46 -0700384
385
386 def _parse_sender_output(self, output):
387 """Parse the log output from the crash_sender script.
388
389 This script can run on the logs from either a mocked or true
390 crash send.
391
392 Args:
393 output: output from the script
394
395 Returns:
396 A dictionary with these values:
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700397 error_type: an error type, if given
Ken Mixter38dfe852010-08-18 15:24:00 -0700398 exec_name: name of executable which crashed
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700399 image_type: type of image ("dev","force-official",...), if given
Michael Krebsfb875d02012-09-13 16:49:50 -0700400 boot_mode: current boot mode ("dev",...), if given
Ken Mixter67ff5622010-09-30 15:32:17 -0700401 meta_path: path to the report metadata file
402 output: the output from the script, copied
Ken Mixter38dfe852010-08-18 15:24:00 -0700403 report_kind: kind of report sent (minidump vs kernel)
Ken Mixter20d9e472010-08-12 10:58:46 -0700404 send_attempt: did the script attempt to send a crash.
405 send_success: if it attempted, was the crash send successful.
Ken Mixterd79140e2010-10-26 14:45:30 -0700406 sig: signature of the report, if given.
Ken Mixter20d9e472010-08-12 10:58:46 -0700407 sleep_time: if it attempted, how long did it sleep before
408 sending (if mocked, how long would it have slept)
Ken Mixter20d9e472010-08-12 10:58:46 -0700409 """
410 sleep_match = re.search('Scheduled to send in (\d+)s', output)
411 send_attempt = sleep_match is not None
412 if send_attempt:
413 sleep_time = int(sleep_match.group(1))
414 else:
415 sleep_time = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700416
Ken Mixter67ff5622010-09-30 15:32:17 -0700417 meta_match = re.search('Metadata: (\S+) \((\S+)\)', output)
418 if meta_match:
419 meta_path = meta_match.group(1)
420 report_kind = meta_match.group(2)
Ken Mixter38dfe852010-08-18 15:24:00 -0700421 else:
Ken Mixter67ff5622010-09-30 15:32:17 -0700422 meta_path = None
Ken Mixter38dfe852010-08-18 15:24:00 -0700423 report_kind = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700424
Ken Mixter67ff5622010-09-30 15:32:17 -0700425 payload_match = re.search('Payload: (\S+)', output)
426 if payload_match:
427 report_payload = payload_match.group(1)
428 else:
429 report_payload = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700430
Ken Mixter38dfe852010-08-18 15:24:00 -0700431 exec_name_match = re.search('Exec name: (\S+)', output)
432 if exec_name_match:
433 exec_name = exec_name_match.group(1)
434 else:
435 exec_name = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700436
Ken Mixter10c48672010-11-01 13:37:08 -0700437 sig_match = re.search('sig: (\S+)', output)
Ken Mixterd79140e2010-10-26 14:45:30 -0700438 if sig_match:
439 sig = sig_match.group(1)
440 else:
441 sig = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700442
443 error_type_match = re.search('Error type: (\S+)', output)
444 if error_type_match:
445 error_type = error_type_match.group(1)
446 else:
447 error_type = None
448
449 image_type_match = re.search('Image type: (\S+)', output)
450 if image_type_match:
451 image_type = image_type_match.group(1)
452 else:
453 image_type = None
454
Michael Krebsfb875d02012-09-13 16:49:50 -0700455 boot_mode_match = re.search('Boot mode: (\S+)', output)
456 if boot_mode_match:
457 boot_mode = boot_mode_match.group(1)
458 else:
459 boot_mode = None
460
Ken Mixter20d9e472010-08-12 10:58:46 -0700461 send_success = 'Mocking successful send' in output
Ken Mixter38dfe852010-08-18 15:24:00 -0700462 return {'exec_name': exec_name,
463 'report_kind': report_kind,
Ken Mixter67ff5622010-09-30 15:32:17 -0700464 'meta_path': meta_path,
465 'report_payload': report_payload,
Ken Mixter38dfe852010-08-18 15:24:00 -0700466 'send_attempt': send_attempt,
Ken Mixter20d9e472010-08-12 10:58:46 -0700467 'send_success': send_success,
Ken Mixterd79140e2010-10-26 14:45:30 -0700468 'sig': sig,
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700469 'error_type': error_type,
470 'image_type': image_type,
Michael Krebsfb875d02012-09-13 16:49:50 -0700471 'boot_mode': boot_mode,
Ken Mixter20d9e472010-08-12 10:58:46 -0700472 'sleep_time': sleep_time,
473 'output': output}
474
475
Ken Mixter654f32e2010-10-20 11:47:31 -0700476 def wait_for_sender_completion(self):
477 """Wait for crash_sender to complete.
478
479 Wait for no crash_sender's last message to be placed in the
480 system log before continuing and for the process to finish.
481 Otherwise we might get only part of the output."""
Eric Lie7c4cab2011-01-05 14:39:19 -0800482 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700483 lambda: self._log_reader.can_find('crash_sender done.'),
484 timeout=60,
485 exception=error.TestError(
486 'Timeout waiting for crash_sender to emit done: ' +
487 self._log_reader.get_logs()))
Eric Lie7c4cab2011-01-05 14:39:19 -0800488 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700489 lambda: utils.system('pgrep crash_sender',
490 ignore_status=True) != 0,
491 timeout=60,
492 exception=error.TestError(
493 'Timeout waiting for crash_sender to finish: ' +
494 self._log_reader.get_logs()))
495
496
Ken Mixter20d9e472010-08-12 10:58:46 -0700497 def _call_sender_one_crash(self,
498 send_success=True,
499 reports_enabled=True,
500 username='root',
Ken Mixter38dfe852010-08-18 15:24:00 -0700501 report=None):
Ken Mixter20d9e472010-08-12 10:58:46 -0700502 """Call the crash sender script to mock upload one crash.
503
504 Args:
505 send_success: Mock a successful send if true
506 reports_enabled: Has the user consented to sending crash reports.
507 username: user to emulate a crash from
Ken Mixter38dfe852010-08-18 15:24:00 -0700508 report: report to use for crash, if None we create one.
Ken Mixter20d9e472010-08-12 10:58:46 -0700509
510 Returns:
511 Returns a dictionary describing the result with the keys
512 from _parse_sender_output, as well as:
Ken Mixter38dfe852010-08-18 15:24:00 -0700513 report_exists: does the minidump still exist after calling
Ken Mixter20d9e472010-08-12 10:58:46 -0700514 send script
515 rate_count: how many crashes have been uploaded in the past
516 24 hours.
517 """
Ken Mixter38dfe852010-08-18 15:24:00 -0700518 report = self._prepare_sender_one_crash(send_success,
519 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700520 report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700521 self._log_reader.set_start_by_current()
522 script_output = utils.system_output(
523 '/bin/sh -c "%s" 2>&1' % self._CRASH_SENDER_PATH,
524 ignore_status=True)
Ken Mixter654f32e2010-10-20 11:47:31 -0700525 self.wait_for_sender_completion()
Ken Mixter20d9e472010-08-12 10:58:46 -0700526 output = self._log_reader.get_logs()
527 logging.debug('Crash sender message output:\n' + output)
528 if script_output != '':
529 raise error.TestFail(
530 'Unexpected crash_sender stdout/stderr: ' + script_output)
531
Ken Mixter38dfe852010-08-18 15:24:00 -0700532 if os.path.exists(report):
533 report_exists = True
534 os.remove(report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700535 else:
Ken Mixter38dfe852010-08-18 15:24:00 -0700536 report_exists = False
Ken Mixter20d9e472010-08-12 10:58:46 -0700537 if os.path.exists(self._CRASH_SENDER_RATE_DIR):
538 rate_count = len(os.listdir(self._CRASH_SENDER_RATE_DIR))
539 else:
540 rate_count = 0
541
542 result = self._parse_sender_output(output)
Ken Mixter38dfe852010-08-18 15:24:00 -0700543 result['report_exists'] = report_exists
Ken Mixter20d9e472010-08-12 10:58:46 -0700544 result['rate_count'] = rate_count
545
546 # Show the result for debugging but remove 'output' key
547 # since it's large and earlier in debug output.
548 debug_result = dict(result)
549 del debug_result['output']
550 logging.debug('Result of send (besides output): %s' % debug_result)
551
552 return result
553
554
Ken Mixterddcd92d2010-11-01 19:07:08 -0700555 def _replace_crash_reporter_filter_in(self, new_parameter):
Simon Glassa47f0d72011-03-15 11:45:32 -0700556 """Replaces the --filter_in= parameter of the crash reporter.
557
558 The kernel is set up to call the crash reporter with the core dump
559 as stdin when a process dies. This function adds a filter to the
560 command line used to call the crash reporter. This is used to ignore
561 crashes in which we have no interest.
562
563 This removes any --filter_in= parameter and optionally replaces it
564 with a new one.
565
566 Args:
567 new_parameter: This is parameter to add to the command line
568 instead of the --filter_in=... that was there.
569 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700570 core_pattern = utils.read_file(self._CORE_PATTERN)[:-1]
571 core_pattern = re.sub('--filter_in=\S*\s*', '',
572 core_pattern).rstrip()
573 if new_parameter:
574 core_pattern += ' ' + new_parameter
575 utils.system('echo "%s" > %s' % (core_pattern, self._CORE_PATTERN))
576
577
578 def enable_crash_filtering(self, name):
Simon Glassa47f0d72011-03-15 11:45:32 -0700579 """Add a --filter_in argument to the kernel core dump cmdline.
580
581 Args:
582 name: Filter text to use. This is passed as a --filter_in
583 argument to the crash reporter.
584 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700585 self._replace_crash_reporter_filter_in('--filter_in=' + name)
586
587
588 def disable_crash_filtering(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700589 """Remove the --filter_in argument from the kernel core dump cmdline.
590
591 Next time the crash reporter is invoked (due to a crash) it will not
592 receive a --filter_in paramter."""
Ken Mixterddcd92d2010-11-01 19:07:08 -0700593 self._replace_crash_reporter_filter_in('')
594
595
Ken Mixter20d9e472010-08-12 10:58:46 -0700596 def initialize(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700597 """Initalize the test."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700598 test.test.initialize(self)
Eric Lie7c4cab2011-01-05 14:39:19 -0800599 self._log_reader = cros_logging.LogReader()
Ken Mixter38dfe852010-08-18 15:24:00 -0700600 self._leave_crash_sending = True
Ken Mixter67ff5622010-09-30 15:32:17 -0700601 self._automatic_consent_saving = True
Ken Mixterddcd92d2010-11-01 19:07:08 -0700602 self.enable_crash_filtering('none')
Thieu Lec16253b2011-03-03 11:13:54 -0800603 self._set_crash_test_in_progress(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700604
605
606 def cleanup(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700607 """Cleanup after the test.
608
609 We reset things back to the way we think they should be. This is
610 intended to allow the system to continue normal operation.
611
612 Some variables silently change the behavior:
613 _automatic_consent_saving: if True, we pop the consent file.
614 _leave_crash_sending: True to enable crash sending, False to
615 disable it
616 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700617 self._reset_rate_limiting()
618 self._clear_spooled_crashes()
Ken Mixter4f619652010-10-18 12:11:18 -0700619 self._set_system_sending(self._leave_crash_sending)
Ken Mixter20d9e472010-08-12 10:58:46 -0700620 self._set_sending_mock(mock_enabled=False)
Ken Mixter67ff5622010-09-30 15:32:17 -0700621 if self._automatic_consent_saving:
622 self._pop_consent()
Ken Mixterddcd92d2010-11-01 19:07:08 -0700623 self.disable_crash_filtering()
Thieu Lec16253b2011-03-03 11:13:54 -0800624 self._set_crash_test_in_progress(False)
Ken Mixter20d9e472010-08-12 10:58:46 -0700625 test.test.cleanup(self)
626
627
Ken Mixter38dfe852010-08-18 15:24:00 -0700628 def run_crash_tests(self,
629 test_names,
630 initialize_crash_reporter=False,
631 clear_spool_first=True,
632 must_run_all=True):
633 """Run crash tests defined in this class.
634
635 Args:
Simon Glassa47f0d72011-03-15 11:45:32 -0700636 test_names: Array of test names.
637 initialize_crash_reporter: Should set up crash reporter for every
638 run.
639 clear_spool_first: Clear all spooled user/system crashes before
640 starting the test.
641 must_run_all: Should make sure every test in this class is
642 mentioned in test_names.
Ken Mixter38dfe852010-08-18 15:24:00 -0700643 """
Ken Mixter67ff5622010-09-30 15:32:17 -0700644 if self._automatic_consent_saving:
645 self._push_consent()
Ken Mixter20d9e472010-08-12 10:58:46 -0700646
Ken Mixter38dfe852010-08-18 15:24:00 -0700647 if must_run_all:
648 # Sanity check test_names is complete
649 for attr in dir(self):
650 if attr.find('_test_') == 0:
651 test_name = attr[6:]
652 if not test_name in test_names:
653 raise error.TestError('Test %s is missing' % test_name)
Ken Mixter20d9e472010-08-12 10:58:46 -0700654
655 for test_name in test_names:
656 logging.info(('=' * 20) + ('Running %s' % test_name) + ('=' * 20))
Ken Mixter38dfe852010-08-18 15:24:00 -0700657 if initialize_crash_reporter:
658 self._initialize_crash_reporter()
Ken Mixter4f619652010-10-18 12:11:18 -0700659 # Disable crash_sender from running, kill off any running ones, but
660 # set environment so crash_sender may run as a child process.
661 self._set_system_sending(False)
662 self._set_child_sending(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700663 self._kill_running_sender()
664 self._reset_rate_limiting()
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700665 # Default to not overriding for unofficial versions.
666 self._set_force_official(False)
Michael Krebsfb875d02012-09-13 16:49:50 -0700667 # Default to not pretending we're in developer mode.
668 self._set_mock_developer_mode(False)
Ken Mixter38dfe852010-08-18 15:24:00 -0700669 if clear_spool_first:
670 self._clear_spooled_crashes()
Simon Glassa47f0d72011-03-15 11:45:32 -0700671
672 # Call the test function
Ken Mixter20d9e472010-08-12 10:58:46 -0700673 getattr(self, '_test_' + test_name)()