blob: 51d1a0e1b2dbced709fdd9efbdb85b3661145b31 [file] [log] [blame]
barfab@chromium.orgb6d29932012-04-11 09:46:43 +02001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Ken Mixter20d9e472010-08-12 10:58:46 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Dale Curtis497c2cb2010-11-16 13:44:33 -08005import logging, os, re, shutil
barfab@chromium.orgb6d29932012-04-11 09:46:43 +02006
7import common, cros_logging
Eric Lie7c4cab2011-01-05 14:39:19 -08008from autotest_lib.client.bin import test, utils
9from autotest_lib.client.common_lib import error
Ken Mixter20d9e472010-08-12 10:58:46 -070010
11
12class CrashTest(test.test):
Simon Glassa47f0d72011-03-15 11:45:32 -070013 """
14 This class deals with running crash tests, which are tests which crash a
15 user-space program (or the whole machine) and generate a core dump. We
16 want to check that the correct crash dump is available and can be
17 retrieved.
18
19 Chromium OS has a crash sender which checks for new crash data and sends
20 it to a server. This crash data is used to track software quality and find
21 bugs. The system crash sender normally is always running, but can be paused
22 by creating _PAUSE_FILE. When crash sender sees this, it pauses operation.
23
24 The pid of the system crash sender is stored in _CRASH_SENDER_RUN_PATH so
25 we can use this to kill the system crash sender for when we want to run
26 our own.
27
28 For testing purposes we sometimes want to run the crash sender manually.
29 In this case we can set 'OVERRIDE_PAUSE_SENDING=1' in the environment and
30 run the crash sender manually (as a child process).
31
32 Also for testing we sometimes want to mock out the crash sender, and just
33 have it pretend to succeed or fail. The _MOCK_CRASH_SENDING file is used
34 for this. If it doesn't exist, then the crash sender runs normally. If
35 it exists but is empty, the crash sender will succeed (but actually do
36 nothing). If the file contains something, then the crash sender will fail.
37
38 If the user consents to sending crash tests, then the _CONSENT_FILE will
39 exist in the home directory. This test needs to create this file for the
40 crash sending to work.
41
42 Crash reports are rate limited to a certain number of reports each 24
43 hours. If the maximum number has already been sent then reports are held
44 until later. This is administered by a directory _CRASH_SENDER_RATE_DIR
45 which contains one temporary file for each time a report is sent.
46
47 The class provides the ability to push a consent file. This disables
48 consent for this test but allows it to be popped back at later. This
49 makes nested tests easier. If _automatic_consent_saving is True (the
50 default) then consent will be pushed at the start and popped at the end.
51
52 Interesting variables:
53 _log_reader: the log reader used for reading log files
54 _leave_crash_sending: True to enable crash sending on exit from the
55 test, False to disable it. (Default True).
56 _automatic_consent_saving: True to push the consent at the start of
57 the test and pop it afterwards. (Default True).
58
59 Useful places to look for more information are:
60
61 chromeos/src/platform/crash-reporter/crash_sender
62 - sender script which crash crash reporter to create reports, then
63
64 chromeos/src/platform/crash-reporter/
65 - crash reporter program
66 """
67
Ken Mixter20d9e472010-08-12 10:58:46 -070068
69 _CONSENT_FILE = '/home/chronos/Consent To Send Stats'
Julian Pastarmovd56badb2011-07-15 20:24:45 +020070 _POLICY_FILE = '/var/lib/whitelist/policy'
71 _OWNER_KEY_FILE = '/var/lib/whitelist/owner.key'
Ken Mixterddcd92d2010-11-01 19:07:08 -070072 _CORE_PATTERN = '/proc/sys/kernel/core_pattern'
Ken Mixter20d9e472010-08-12 10:58:46 -070073 _CRASH_REPORTER_PATH = '/sbin/crash_reporter'
74 _CRASH_SENDER_PATH = '/sbin/crash_sender'
75 _CRASH_SENDER_RATE_DIR = '/var/lib/crash_sender'
76 _CRASH_SENDER_RUN_PATH = '/var/run/crash_sender.pid'
Thieu Lec16253b2011-03-03 11:13:54 -080077 _CRASH_TEST_IN_PROGRESS = '/tmp/crash-test-in-progress'
Ken Mixter20d9e472010-08-12 10:58:46 -070078 _MOCK_CRASH_SENDING = '/tmp/mock-crash-sending'
Ken Mixter38dfe852010-08-18 15:24:00 -070079 _PAUSE_FILE = '/var/lib/crash_sender_paused'
Ken Mixter20d9e472010-08-12 10:58:46 -070080 _SYSTEM_CRASH_DIR = '/var/spool/crash'
Mike Frysingerded8de72013-05-29 20:45:48 -040081 _FALLBACK_USER_CRASH_DIR = '/home/chronos/crash'
82 _USER_CRASH_DIRS = '/home/chronos/u-*/crash'
Ken Mixter20d9e472010-08-12 10:58:46 -070083
Ken Mixter4f619652010-10-18 12:11:18 -070084 def _set_system_sending(self, is_enabled):
85 """Sets whether or not the system crash_sender is allowed to run.
86
Simon Glassa47f0d72011-03-15 11:45:32 -070087 This is done by creating or removing _PAUSE_FILE.
88
Ken Mixter4f619652010-10-18 12:11:18 -070089 crash_sender may still be allowed to run if _set_child_sending is
Simon Glassa47f0d72011-03-15 11:45:32 -070090 called with True and it is run as a child process.
91
92 Args:
93 is_enabled: True to enable crash_sender, False to disable it.
94 """
Ken Mixter20d9e472010-08-12 10:58:46 -070095 if is_enabled:
96 if os.path.exists(self._PAUSE_FILE):
97 os.remove(self._PAUSE_FILE)
98 else:
99 utils.system('touch ' + self._PAUSE_FILE)
100
101
Ken Mixter4f619652010-10-18 12:11:18 -0700102 def _set_child_sending(self, is_enabled):
Simon Glassa47f0d72011-03-15 11:45:32 -0700103 """Overrides crash sending enabling for child processes.
104
105 When the system crash sender is disabled this test can manually run
106 the crash sender as a child process. Normally this would do nothing,
107 but this function sets up crash_sender to ignore its disabled status
108 and do its job.
109
110 Args:
111 is_enabled: True to enable crash sending for child processes.
112 """
Ken Mixter4f619652010-10-18 12:11:18 -0700113 if is_enabled:
114 os.environ['OVERRIDE_PAUSE_SENDING'] = "1"
115 else:
116 del os.environ['OVERRIDE_PAUSE_SENDING']
117
118
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700119 def _set_force_official(self, is_enabled):
120 """Sets whether or not reports will upload for unofficial versions.
121
122 Normally, crash reports are only uploaded for official build
123 versions. If the override is set, however, they will also be
124 uploaded for unofficial versions.
125
126 Args:
127 is_enabled: True to enable uploading for unofficial versions.
128 """
129 if is_enabled:
130 os.environ['FORCE_OFFICIAL'] = "1"
131 elif os.environ.get('FORCE_OFFICIAL'):
132 del os.environ['FORCE_OFFICIAL']
133
134
Michael Krebsfb875d02012-09-13 16:49:50 -0700135 def _set_mock_developer_mode(self, is_enabled):
136 """Sets whether or not we should pretend we booted in developer mode.
137
138 Args:
139 is_enabled: True to pretend we are in developer mode.
140 """
141 if is_enabled:
142 os.environ['MOCK_DEVELOPER_MODE'] = "1"
143 elif os.environ.get('MOCK_DEVELOPER_MODE'):
144 del os.environ['MOCK_DEVELOPER_MODE']
145
146
Ken Mixter20d9e472010-08-12 10:58:46 -0700147 def _reset_rate_limiting(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700148 """Reset the count of crash reports sent today.
149
150 This clears the contents of the rate limiting directory which has
151 the effect of reseting our count of crash reports sent.
152 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700153 utils.system('rm -rf ' + self._CRASH_SENDER_RATE_DIR)
154
155
156 def _clear_spooled_crashes(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700157 """Clears system and user crash directories.
158
159 This will remove all crash reports which are waiting to be sent.
160 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700161 utils.system('rm -rf ' + self._SYSTEM_CRASH_DIR)
Mike Frysingerded8de72013-05-29 20:45:48 -0400162 utils.system('rm -rf %s %s' % (self._USER_CRASH_DIRS,
163 self._FALLBACK_USER_CRASH_DIR))
Ken Mixter20d9e472010-08-12 10:58:46 -0700164
165
166 def _kill_running_sender(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700167 """Kill the the crash_sender process if running.
168
169 We use the PID file to find the process ID, then kill it with signal 9.
170 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700171 if not os.path.exists(self._CRASH_SENDER_RUN_PATH):
172 return
173 running_pid = int(utils.read_file(self._CRASH_SENDER_RUN_PATH))
174 logging.warning('Detected running crash sender (%d), killing' %
175 running_pid)
176 utils.system('kill -9 %d' % running_pid)
177 os.remove(self._CRASH_SENDER_RUN_PATH)
178
179
180 def _set_sending_mock(self, mock_enabled, send_success=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700181 """Enables / disables mocking of the sending process.
182
183 This uses the _MOCK_CRASH_SENDING file to achieve its aims. See notes
184 at the top.
185
186 Args:
187 mock_enabled: If True, mocking is enabled, else it is disabled.
188 send_success: If mock_enabled this is True for the mocking to
189 indicate success, False to indicate failure.
190 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700191 if mock_enabled:
192 if send_success:
193 data = ''
194 else:
195 data = '1'
196 logging.info('Setting sending mock')
197 utils.open_write_close(self._MOCK_CRASH_SENDING, data)
198 else:
199 utils.system('rm -f ' + self._MOCK_CRASH_SENDING)
200
201
202 def _set_consent(self, has_consent):
Simon Glassa47f0d72011-03-15 11:45:32 -0700203 """Sets whether or not we have consent to send crash reports.
204
205 This creates or deletes the _CONSENT_FILE to control whether
206 crash_sender will consider that it has consent to send crash reports.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200207 It also copies a policy blob with the proper policy setting.
Simon Glassa47f0d72011-03-15 11:45:32 -0700208
209 Args:
210 has_consent: True to indicate consent, False otherwise
211 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700212 if has_consent:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700213 # Create policy file that enables metrics/consent.
214 shutil.copy('/usr/local/autotest/cros/mock_metrics_on.policy',
215 self._POLICY_FILE)
216 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
217 self._OWNER_KEY_FILE)
218 # Create deprecated consent file. This is created *after* the
219 # policy file in order to avoid a race condition where chrome
220 # might remove the consent file if the policy's not set yet.
Michael Krebse9028fc2011-08-19 15:00:00 -0700221 # We create it as a temp file first in order to make the creation
222 # of the consent file, owned by chronos, atomic.
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700223 # See crosbug.com/18413.
Michael Krebse9028fc2011-08-19 15:00:00 -0700224 temp_file = self._CONSENT_FILE + '.tmp';
225 utils.open_write_close(temp_file, 'test-consent')
226 utils.system('chown chronos:chronos "%s"' % (temp_file))
227 shutil.move(temp_file, self._CONSENT_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700228 logging.info('Created ' + self._CONSENT_FILE)
229 else:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700230 # Create policy file that disables metrics/consent.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200231 shutil.copy('/usr/local/autotest/cros/mock_metrics_off.policy',
232 self._POLICY_FILE)
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700233 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
234 self._OWNER_KEY_FILE)
235 # Remove deprecated consent file.
236 utils.system('rm -f "%s"' % (self._CONSENT_FILE))
Ken Mixter20d9e472010-08-12 10:58:46 -0700237
238
Thieu Lec16253b2011-03-03 11:13:54 -0800239 def _set_crash_test_in_progress(self, in_progress):
240 if in_progress:
241 utils.open_write_close(self._CRASH_TEST_IN_PROGRESS, 'in-progress')
242 logging.info('Created ' + self._CRASH_TEST_IN_PROGRESS)
243 else:
244 utils.system('rm -f "%s"' % (self._CRASH_TEST_IN_PROGRESS))
245
246
Ken Mixter20d9e472010-08-12 10:58:46 -0700247 def _get_pushed_consent_file_path(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700248 """Returns filename of the pushed consent file."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700249 return os.path.join(self.bindir, 'pushed_consent')
250
251
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200252 def _get_pushed_policy_file_path(self):
253 """Returns filename of the pushed policy file."""
254 return os.path.join(self.bindir, 'pushed_policy')
255
256
257 def _get_pushed_owner_key_file_path(self):
258 """Returns filename of the pushed owner.key file."""
259 return os.path.join(self.bindir, 'pushed_owner_key')
260
261
Ken Mixter20d9e472010-08-12 10:58:46 -0700262 def _push_consent(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700263 """Push the consent file, thus disabling consent.
264
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200265 The consent files can be created in the new test if required. Call
Simon Glassa47f0d72011-03-15 11:45:32 -0700266 _pop_consent() to restore the original state.
267 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700268 if os.path.exists(self._CONSENT_FILE):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800269 shutil.move(self._CONSENT_FILE,
270 self._get_pushed_consent_file_path())
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200271 if os.path.exists(self._POLICY_FILE):
272 shutil.move(self._POLICY_FILE,
273 self._get_pushed_policy_file_path())
274 if os.path.exists(self._OWNER_KEY_FILE):
275 shutil.move(self._OWNER_KEY_FILE,
276 self._get_pushed_owner_key_file_path())
Ken Mixter20d9e472010-08-12 10:58:46 -0700277
278
279 def _pop_consent(self):
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200280 """Pop the consent files, enabling/disabling consent as it was before
Simon Glassa47f0d72011-03-15 11:45:32 -0700281 we pushed the consent."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700282 if os.path.exists(self._get_pushed_consent_file_path()):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800283 shutil.move(self._get_pushed_consent_file_path(),
284 self._CONSENT_FILE)
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200285 else:
286 utils.system('rm -f "%s"' % self._CONSENT_FILE)
287 if os.path.exists(self._get_pushed_policy_file_path()):
288 shutil.move(self._get_pushed_policy_file_path(),
289 self._POLICY_FILE)
290 else:
291 utils.system('rm -f "%s"' % self._POLICY_FILE)
292 if os.path.exists(self._get_pushed_owner_key_file_path()):
293 shutil.move(self._get_pushed_owner_key_file_path(),
294 self._OWNER_KEY_FILE)
295 else:
296 utils.system('rm -f "%s"' % self._OWNER_KEY_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700297
298
299 def _get_crash_dir(self, username):
Simon Glassa47f0d72011-03-15 11:45:32 -0700300 """Returns full path to the crash directory for a given username
301
Mike Frysingerded8de72013-05-29 20:45:48 -0400302 This only really works (currently) when no one is logged in. That
303 is OK (currently) as the only test that uses this runs when no one
304 is actually logged in.
305
Simon Glassa47f0d72011-03-15 11:45:32 -0700306 Args:
307 username: username to use:
308 'chronos': Returns user crash directory.
309 'root': Returns system crash directory.
310 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700311 if username == 'chronos':
Mike Frysingerded8de72013-05-29 20:45:48 -0400312 return self._FALLBACK_USER_CRASH_DIR
Ken Mixter20d9e472010-08-12 10:58:46 -0700313 else:
314 return self._SYSTEM_CRASH_DIR
315
316
317 def _initialize_crash_reporter(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700318 """Start up the crash reporter."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700319 utils.system('%s --init --nounclean_check' % self._CRASH_REPORTER_PATH)
Ken Mixterddcd92d2010-11-01 19:07:08 -0700320 # Completely disable crash_reporter from generating crash dumps
321 # while any tests are running, otherwise a crashy system can make
322 # these tests flaky.
323 self.enable_crash_filtering('none')
Ken Mixter20d9e472010-08-12 10:58:46 -0700324
325
Ken Mixter67ff5622010-09-30 15:32:17 -0700326 def write_crash_dir_entry(self, name, contents):
Simon Glassa47f0d72011-03-15 11:45:32 -0700327 """Writes an empty file to the system crash directory.
328
329 This writes a file to _SYSTEM_CRASH_DIR with the given name. This is
330 used to insert new crash dump files for testing purposes.
331
332 Args:
333 name: Name of file to write.
334 contents: String to write to the file.
335 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700336 entry = os.path.join(self._SYSTEM_CRASH_DIR, name)
337 if not os.path.exists(self._SYSTEM_CRASH_DIR):
338 os.makedirs(self._SYSTEM_CRASH_DIR)
Ken Mixter67ff5622010-09-30 15:32:17 -0700339 utils.open_write_close(entry, contents)
Ken Mixter20d9e472010-08-12 10:58:46 -0700340 return entry
341
342
Ken Mixterdee4e292010-12-14 17:45:21 -0800343 def write_fake_meta(self, name, exec_name, payload, log=None,
344 complete=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700345 """Writes a fake meta entry to the system crash directory.
346
347 Args:
348 name: Name of file to write.
349 exec_name: Value for exec_name item.
350 payload: Value for payload item.
351 log: Value for log item.
352 complete: True to close off the record, otherwise leave it
353 incomplete.
354 """
Ken Mixter1a894e02010-10-28 15:42:52 -0700355 last_line = ''
356 if complete:
357 last_line = 'done=1\n'
Ken Mixterdee4e292010-12-14 17:45:21 -0800358 contents = ('exec_name=%s\n'
359 'ver=my_ver\n'
360 'payload=%s\n'
361 '%s' % (exec_name, payload,
362 last_line))
363 if log:
364 contents = ('log=%s\n' % log) + contents
365 return self.write_crash_dir_entry(name, contents)
Ken Mixter67ff5622010-09-30 15:32:17 -0700366
367
Ken Mixter20d9e472010-08-12 10:58:46 -0700368 def _prepare_sender_one_crash(self,
369 send_success,
370 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700371 report):
Simon Glassa47f0d72011-03-15 11:45:32 -0700372 """Create metadata for a fake crash report.
373
374 This enabled mocking of the crash sender, then creates a fake
375 crash report for testing purposes.
376
377 Args:
378 send_success: True to make the crash_sender success, False to make
379 it fail.
380 reports_enabled: True to enable consent to that reports will be
381 sent.
382 report: Report to use for crash, if None we create one.
383 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700384 self._set_sending_mock(mock_enabled=True, send_success=send_success)
385 self._set_consent(reports_enabled)
Ken Mixter38dfe852010-08-18 15:24:00 -0700386 if report is None:
Ken Mixter1a894e02010-10-28 15:42:52 -0700387 payload = self.write_crash_dir_entry('fake.dmp', '')
388 report = self.write_fake_meta('fake.meta', 'fake', payload)
Ken Mixter38dfe852010-08-18 15:24:00 -0700389 return report
Ken Mixter20d9e472010-08-12 10:58:46 -0700390
391
392 def _parse_sender_output(self, output):
393 """Parse the log output from the crash_sender script.
394
395 This script can run on the logs from either a mocked or true
396 crash send.
397
398 Args:
399 output: output from the script
400
401 Returns:
402 A dictionary with these values:
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700403 error_type: an error type, if given
Ken Mixter38dfe852010-08-18 15:24:00 -0700404 exec_name: name of executable which crashed
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700405 image_type: type of image ("dev","force-official",...), if given
Michael Krebsfb875d02012-09-13 16:49:50 -0700406 boot_mode: current boot mode ("dev",...), if given
Ken Mixter67ff5622010-09-30 15:32:17 -0700407 meta_path: path to the report metadata file
408 output: the output from the script, copied
Ken Mixter38dfe852010-08-18 15:24:00 -0700409 report_kind: kind of report sent (minidump vs kernel)
Ken Mixter20d9e472010-08-12 10:58:46 -0700410 send_attempt: did the script attempt to send a crash.
411 send_success: if it attempted, was the crash send successful.
Ken Mixterd79140e2010-10-26 14:45:30 -0700412 sig: signature of the report, if given.
Ken Mixter20d9e472010-08-12 10:58:46 -0700413 sleep_time: if it attempted, how long did it sleep before
414 sending (if mocked, how long would it have slept)
Ken Mixter20d9e472010-08-12 10:58:46 -0700415 """
416 sleep_match = re.search('Scheduled to send in (\d+)s', output)
417 send_attempt = sleep_match is not None
418 if send_attempt:
419 sleep_time = int(sleep_match.group(1))
420 else:
421 sleep_time = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700422
Ken Mixter67ff5622010-09-30 15:32:17 -0700423 meta_match = re.search('Metadata: (\S+) \((\S+)\)', output)
424 if meta_match:
425 meta_path = meta_match.group(1)
426 report_kind = meta_match.group(2)
Ken Mixter38dfe852010-08-18 15:24:00 -0700427 else:
Ken Mixter67ff5622010-09-30 15:32:17 -0700428 meta_path = None
Ken Mixter38dfe852010-08-18 15:24:00 -0700429 report_kind = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700430
Ken Mixter67ff5622010-09-30 15:32:17 -0700431 payload_match = re.search('Payload: (\S+)', output)
432 if payload_match:
433 report_payload = payload_match.group(1)
434 else:
435 report_payload = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700436
Ken Mixter38dfe852010-08-18 15:24:00 -0700437 exec_name_match = re.search('Exec name: (\S+)', output)
438 if exec_name_match:
439 exec_name = exec_name_match.group(1)
440 else:
441 exec_name = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700442
Ken Mixter10c48672010-11-01 13:37:08 -0700443 sig_match = re.search('sig: (\S+)', output)
Ken Mixterd79140e2010-10-26 14:45:30 -0700444 if sig_match:
445 sig = sig_match.group(1)
446 else:
447 sig = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700448
449 error_type_match = re.search('Error type: (\S+)', output)
450 if error_type_match:
451 error_type = error_type_match.group(1)
452 else:
453 error_type = None
454
455 image_type_match = re.search('Image type: (\S+)', output)
456 if image_type_match:
457 image_type = image_type_match.group(1)
458 else:
459 image_type = None
460
Michael Krebsfb875d02012-09-13 16:49:50 -0700461 boot_mode_match = re.search('Boot mode: (\S+)', output)
462 if boot_mode_match:
463 boot_mode = boot_mode_match.group(1)
464 else:
465 boot_mode = None
466
Ken Mixter20d9e472010-08-12 10:58:46 -0700467 send_success = 'Mocking successful send' in output
Ken Mixter38dfe852010-08-18 15:24:00 -0700468 return {'exec_name': exec_name,
469 'report_kind': report_kind,
Ken Mixter67ff5622010-09-30 15:32:17 -0700470 'meta_path': meta_path,
471 'report_payload': report_payload,
Ken Mixter38dfe852010-08-18 15:24:00 -0700472 'send_attempt': send_attempt,
Ken Mixter20d9e472010-08-12 10:58:46 -0700473 'send_success': send_success,
Ken Mixterd79140e2010-10-26 14:45:30 -0700474 'sig': sig,
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700475 'error_type': error_type,
476 'image_type': image_type,
Michael Krebsfb875d02012-09-13 16:49:50 -0700477 'boot_mode': boot_mode,
Ken Mixter20d9e472010-08-12 10:58:46 -0700478 'sleep_time': sleep_time,
479 'output': output}
480
481
Ken Mixter654f32e2010-10-20 11:47:31 -0700482 def wait_for_sender_completion(self):
483 """Wait for crash_sender to complete.
484
485 Wait for no crash_sender's last message to be placed in the
486 system log before continuing and for the process to finish.
487 Otherwise we might get only part of the output."""
Eric Lie7c4cab2011-01-05 14:39:19 -0800488 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700489 lambda: self._log_reader.can_find('crash_sender done.'),
490 timeout=60,
491 exception=error.TestError(
492 'Timeout waiting for crash_sender to emit done: ' +
493 self._log_reader.get_logs()))
Eric Lie7c4cab2011-01-05 14:39:19 -0800494 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700495 lambda: utils.system('pgrep crash_sender',
496 ignore_status=True) != 0,
497 timeout=60,
498 exception=error.TestError(
499 'Timeout waiting for crash_sender to finish: ' +
500 self._log_reader.get_logs()))
501
502
Ken Mixter20d9e472010-08-12 10:58:46 -0700503 def _call_sender_one_crash(self,
504 send_success=True,
505 reports_enabled=True,
506 username='root',
Ken Mixter38dfe852010-08-18 15:24:00 -0700507 report=None):
Ken Mixter20d9e472010-08-12 10:58:46 -0700508 """Call the crash sender script to mock upload one crash.
509
510 Args:
511 send_success: Mock a successful send if true
512 reports_enabled: Has the user consented to sending crash reports.
513 username: user to emulate a crash from
Ken Mixter38dfe852010-08-18 15:24:00 -0700514 report: report to use for crash, if None we create one.
Ken Mixter20d9e472010-08-12 10:58:46 -0700515
516 Returns:
517 Returns a dictionary describing the result with the keys
518 from _parse_sender_output, as well as:
Ken Mixter38dfe852010-08-18 15:24:00 -0700519 report_exists: does the minidump still exist after calling
Ken Mixter20d9e472010-08-12 10:58:46 -0700520 send script
521 rate_count: how many crashes have been uploaded in the past
522 24 hours.
523 """
Ken Mixter38dfe852010-08-18 15:24:00 -0700524 report = self._prepare_sender_one_crash(send_success,
525 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700526 report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700527 self._log_reader.set_start_by_current()
528 script_output = utils.system_output(
529 '/bin/sh -c "%s" 2>&1' % self._CRASH_SENDER_PATH,
530 ignore_status=True)
Ken Mixter654f32e2010-10-20 11:47:31 -0700531 self.wait_for_sender_completion()
Ken Mixter20d9e472010-08-12 10:58:46 -0700532 output = self._log_reader.get_logs()
533 logging.debug('Crash sender message output:\n' + output)
534 if script_output != '':
535 raise error.TestFail(
536 'Unexpected crash_sender stdout/stderr: ' + script_output)
537
Ken Mixter38dfe852010-08-18 15:24:00 -0700538 if os.path.exists(report):
539 report_exists = True
540 os.remove(report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700541 else:
Ken Mixter38dfe852010-08-18 15:24:00 -0700542 report_exists = False
Ken Mixter20d9e472010-08-12 10:58:46 -0700543 if os.path.exists(self._CRASH_SENDER_RATE_DIR):
544 rate_count = len(os.listdir(self._CRASH_SENDER_RATE_DIR))
545 else:
546 rate_count = 0
547
548 result = self._parse_sender_output(output)
Ken Mixter38dfe852010-08-18 15:24:00 -0700549 result['report_exists'] = report_exists
Ken Mixter20d9e472010-08-12 10:58:46 -0700550 result['rate_count'] = rate_count
551
552 # Show the result for debugging but remove 'output' key
553 # since it's large and earlier in debug output.
554 debug_result = dict(result)
555 del debug_result['output']
556 logging.debug('Result of send (besides output): %s' % debug_result)
557
558 return result
559
560
Ken Mixterddcd92d2010-11-01 19:07:08 -0700561 def _replace_crash_reporter_filter_in(self, new_parameter):
Simon Glassa47f0d72011-03-15 11:45:32 -0700562 """Replaces the --filter_in= parameter of the crash reporter.
563
564 The kernel is set up to call the crash reporter with the core dump
565 as stdin when a process dies. This function adds a filter to the
566 command line used to call the crash reporter. This is used to ignore
567 crashes in which we have no interest.
568
569 This removes any --filter_in= parameter and optionally replaces it
570 with a new one.
571
572 Args:
573 new_parameter: This is parameter to add to the command line
574 instead of the --filter_in=... that was there.
575 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700576 core_pattern = utils.read_file(self._CORE_PATTERN)[:-1]
577 core_pattern = re.sub('--filter_in=\S*\s*', '',
578 core_pattern).rstrip()
579 if new_parameter:
580 core_pattern += ' ' + new_parameter
581 utils.system('echo "%s" > %s' % (core_pattern, self._CORE_PATTERN))
582
583
584 def enable_crash_filtering(self, name):
Simon Glassa47f0d72011-03-15 11:45:32 -0700585 """Add a --filter_in argument to the kernel core dump cmdline.
586
587 Args:
588 name: Filter text to use. This is passed as a --filter_in
589 argument to the crash reporter.
590 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700591 self._replace_crash_reporter_filter_in('--filter_in=' + name)
592
593
594 def disable_crash_filtering(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700595 """Remove the --filter_in argument from the kernel core dump cmdline.
596
597 Next time the crash reporter is invoked (due to a crash) it will not
598 receive a --filter_in paramter."""
Ken Mixterddcd92d2010-11-01 19:07:08 -0700599 self._replace_crash_reporter_filter_in('')
600
601
Ken Mixter20d9e472010-08-12 10:58:46 -0700602 def initialize(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700603 """Initalize the test."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700604 test.test.initialize(self)
Eric Lie7c4cab2011-01-05 14:39:19 -0800605 self._log_reader = cros_logging.LogReader()
Ken Mixter38dfe852010-08-18 15:24:00 -0700606 self._leave_crash_sending = True
Ken Mixter67ff5622010-09-30 15:32:17 -0700607 self._automatic_consent_saving = True
Ken Mixterddcd92d2010-11-01 19:07:08 -0700608 self.enable_crash_filtering('none')
Thieu Lec16253b2011-03-03 11:13:54 -0800609 self._set_crash_test_in_progress(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700610
611
612 def cleanup(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700613 """Cleanup after the test.
614
615 We reset things back to the way we think they should be. This is
616 intended to allow the system to continue normal operation.
617
618 Some variables silently change the behavior:
619 _automatic_consent_saving: if True, we pop the consent file.
620 _leave_crash_sending: True to enable crash sending, False to
621 disable it
622 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700623 self._reset_rate_limiting()
624 self._clear_spooled_crashes()
Ken Mixter4f619652010-10-18 12:11:18 -0700625 self._set_system_sending(self._leave_crash_sending)
Ken Mixter20d9e472010-08-12 10:58:46 -0700626 self._set_sending_mock(mock_enabled=False)
Ken Mixter67ff5622010-09-30 15:32:17 -0700627 if self._automatic_consent_saving:
628 self._pop_consent()
Ken Mixterddcd92d2010-11-01 19:07:08 -0700629 self.disable_crash_filtering()
Thieu Lec16253b2011-03-03 11:13:54 -0800630 self._set_crash_test_in_progress(False)
Ken Mixter20d9e472010-08-12 10:58:46 -0700631 test.test.cleanup(self)
632
633
Ken Mixter38dfe852010-08-18 15:24:00 -0700634 def run_crash_tests(self,
635 test_names,
636 initialize_crash_reporter=False,
637 clear_spool_first=True,
638 must_run_all=True):
639 """Run crash tests defined in this class.
640
641 Args:
Simon Glassa47f0d72011-03-15 11:45:32 -0700642 test_names: Array of test names.
643 initialize_crash_reporter: Should set up crash reporter for every
644 run.
645 clear_spool_first: Clear all spooled user/system crashes before
646 starting the test.
647 must_run_all: Should make sure every test in this class is
648 mentioned in test_names.
Ken Mixter38dfe852010-08-18 15:24:00 -0700649 """
Ken Mixter67ff5622010-09-30 15:32:17 -0700650 if self._automatic_consent_saving:
651 self._push_consent()
Ken Mixter20d9e472010-08-12 10:58:46 -0700652
Ken Mixter38dfe852010-08-18 15:24:00 -0700653 if must_run_all:
654 # Sanity check test_names is complete
655 for attr in dir(self):
656 if attr.find('_test_') == 0:
657 test_name = attr[6:]
658 if not test_name in test_names:
659 raise error.TestError('Test %s is missing' % test_name)
Ken Mixter20d9e472010-08-12 10:58:46 -0700660
661 for test_name in test_names:
662 logging.info(('=' * 20) + ('Running %s' % test_name) + ('=' * 20))
Ken Mixter38dfe852010-08-18 15:24:00 -0700663 if initialize_crash_reporter:
664 self._initialize_crash_reporter()
Ken Mixter4f619652010-10-18 12:11:18 -0700665 # Disable crash_sender from running, kill off any running ones, but
666 # set environment so crash_sender may run as a child process.
667 self._set_system_sending(False)
668 self._set_child_sending(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700669 self._kill_running_sender()
670 self._reset_rate_limiting()
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700671 # Default to not overriding for unofficial versions.
672 self._set_force_official(False)
Michael Krebsfb875d02012-09-13 16:49:50 -0700673 # Default to not pretending we're in developer mode.
674 self._set_mock_developer_mode(False)
Ken Mixter38dfe852010-08-18 15:24:00 -0700675 if clear_spool_first:
676 self._clear_spooled_crashes()
Simon Glassa47f0d72011-03-15 11:45:32 -0700677
678 # Call the test function
Ken Mixter20d9e472010-08-12 10:58:46 -0700679 getattr(self, '_test_' + test_name)()