blob: 31bab1d0075cf8a6083d88bbd3c0a1a1c67242b4 [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
Ken Mixter20d9e472010-08-12 10:58:46 -0700134 def _reset_rate_limiting(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700135 """Reset the count of crash reports sent today.
136
137 This clears the contents of the rate limiting directory which has
138 the effect of reseting our count of crash reports sent.
139 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700140 utils.system('rm -rf ' + self._CRASH_SENDER_RATE_DIR)
141
142
143 def _clear_spooled_crashes(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700144 """Clears system and user crash directories.
145
146 This will remove all crash reports which are waiting to be sent.
147 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700148 utils.system('rm -rf ' + self._SYSTEM_CRASH_DIR)
149 utils.system('rm -rf ' + self._USER_CRASH_DIR)
150
151
152 def _kill_running_sender(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700153 """Kill the the crash_sender process if running.
154
155 We use the PID file to find the process ID, then kill it with signal 9.
156 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700157 if not os.path.exists(self._CRASH_SENDER_RUN_PATH):
158 return
159 running_pid = int(utils.read_file(self._CRASH_SENDER_RUN_PATH))
160 logging.warning('Detected running crash sender (%d), killing' %
161 running_pid)
162 utils.system('kill -9 %d' % running_pid)
163 os.remove(self._CRASH_SENDER_RUN_PATH)
164
165
166 def _set_sending_mock(self, mock_enabled, send_success=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700167 """Enables / disables mocking of the sending process.
168
169 This uses the _MOCK_CRASH_SENDING file to achieve its aims. See notes
170 at the top.
171
172 Args:
173 mock_enabled: If True, mocking is enabled, else it is disabled.
174 send_success: If mock_enabled this is True for the mocking to
175 indicate success, False to indicate failure.
176 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700177 if mock_enabled:
178 if send_success:
179 data = ''
180 else:
181 data = '1'
182 logging.info('Setting sending mock')
183 utils.open_write_close(self._MOCK_CRASH_SENDING, data)
184 else:
185 utils.system('rm -f ' + self._MOCK_CRASH_SENDING)
186
187
188 def _set_consent(self, has_consent):
Simon Glassa47f0d72011-03-15 11:45:32 -0700189 """Sets whether or not we have consent to send crash reports.
190
191 This creates or deletes the _CONSENT_FILE to control whether
192 crash_sender will consider that it has consent to send crash reports.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200193 It also copies a policy blob with the proper policy setting.
Simon Glassa47f0d72011-03-15 11:45:32 -0700194
195 Args:
196 has_consent: True to indicate consent, False otherwise
197 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700198 if has_consent:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700199 # Create policy file that enables metrics/consent.
200 shutil.copy('/usr/local/autotest/cros/mock_metrics_on.policy',
201 self._POLICY_FILE)
202 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
203 self._OWNER_KEY_FILE)
204 # Create deprecated consent file. This is created *after* the
205 # policy file in order to avoid a race condition where chrome
206 # might remove the consent file if the policy's not set yet.
Michael Krebse9028fc2011-08-19 15:00:00 -0700207 # We create it as a temp file first in order to make the creation
208 # of the consent file, owned by chronos, atomic.
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700209 # See crosbug.com/18413.
Michael Krebse9028fc2011-08-19 15:00:00 -0700210 temp_file = self._CONSENT_FILE + '.tmp';
211 utils.open_write_close(temp_file, 'test-consent')
212 utils.system('chown chronos:chronos "%s"' % (temp_file))
213 shutil.move(temp_file, self._CONSENT_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700214 logging.info('Created ' + self._CONSENT_FILE)
215 else:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700216 # Create policy file that disables metrics/consent.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200217 shutil.copy('/usr/local/autotest/cros/mock_metrics_off.policy',
218 self._POLICY_FILE)
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700219 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
220 self._OWNER_KEY_FILE)
221 # Remove deprecated consent file.
222 utils.system('rm -f "%s"' % (self._CONSENT_FILE))
Ken Mixter20d9e472010-08-12 10:58:46 -0700223
224
Thieu Lec16253b2011-03-03 11:13:54 -0800225 def _set_crash_test_in_progress(self, in_progress):
226 if in_progress:
227 utils.open_write_close(self._CRASH_TEST_IN_PROGRESS, 'in-progress')
228 logging.info('Created ' + self._CRASH_TEST_IN_PROGRESS)
229 else:
230 utils.system('rm -f "%s"' % (self._CRASH_TEST_IN_PROGRESS))
231
232
Ken Mixter20d9e472010-08-12 10:58:46 -0700233 def _get_pushed_consent_file_path(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700234 """Returns filename of the pushed consent file."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700235 return os.path.join(self.bindir, 'pushed_consent')
236
237
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200238 def _get_pushed_policy_file_path(self):
239 """Returns filename of the pushed policy file."""
240 return os.path.join(self.bindir, 'pushed_policy')
241
242
243 def _get_pushed_owner_key_file_path(self):
244 """Returns filename of the pushed owner.key file."""
245 return os.path.join(self.bindir, 'pushed_owner_key')
246
247
Ken Mixter20d9e472010-08-12 10:58:46 -0700248 def _push_consent(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700249 """Push the consent file, thus disabling consent.
250
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200251 The consent files can be created in the new test if required. Call
Simon Glassa47f0d72011-03-15 11:45:32 -0700252 _pop_consent() to restore the original state.
253 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700254 if os.path.exists(self._CONSENT_FILE):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800255 shutil.move(self._CONSENT_FILE,
256 self._get_pushed_consent_file_path())
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200257 if os.path.exists(self._POLICY_FILE):
258 shutil.move(self._POLICY_FILE,
259 self._get_pushed_policy_file_path())
260 if os.path.exists(self._OWNER_KEY_FILE):
261 shutil.move(self._OWNER_KEY_FILE,
262 self._get_pushed_owner_key_file_path())
Ken Mixter20d9e472010-08-12 10:58:46 -0700263
264
265 def _pop_consent(self):
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200266 """Pop the consent files, enabling/disabling consent as it was before
Simon Glassa47f0d72011-03-15 11:45:32 -0700267 we pushed the consent."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700268 if os.path.exists(self._get_pushed_consent_file_path()):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800269 shutil.move(self._get_pushed_consent_file_path(),
270 self._CONSENT_FILE)
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200271 else:
272 utils.system('rm -f "%s"' % self._CONSENT_FILE)
273 if os.path.exists(self._get_pushed_policy_file_path()):
274 shutil.move(self._get_pushed_policy_file_path(),
275 self._POLICY_FILE)
276 else:
277 utils.system('rm -f "%s"' % self._POLICY_FILE)
278 if os.path.exists(self._get_pushed_owner_key_file_path()):
279 shutil.move(self._get_pushed_owner_key_file_path(),
280 self._OWNER_KEY_FILE)
281 else:
282 utils.system('rm -f "%s"' % self._OWNER_KEY_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700283
284
285 def _get_crash_dir(self, username):
Simon Glassa47f0d72011-03-15 11:45:32 -0700286 """Returns full path to the crash directory for a given username
287
288 Args:
289 username: username to use:
290 'chronos': Returns user crash directory.
291 'root': Returns system crash directory.
292 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700293 if username == 'chronos':
294 return self._USER_CRASH_DIR
295 else:
296 return self._SYSTEM_CRASH_DIR
297
298
299 def _initialize_crash_reporter(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700300 """Start up the crash reporter."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700301 utils.system('%s --init --nounclean_check' % self._CRASH_REPORTER_PATH)
Ken Mixterddcd92d2010-11-01 19:07:08 -0700302 # Completely disable crash_reporter from generating crash dumps
303 # while any tests are running, otherwise a crashy system can make
304 # these tests flaky.
305 self.enable_crash_filtering('none')
Ken Mixter20d9e472010-08-12 10:58:46 -0700306
307
Ken Mixter67ff5622010-09-30 15:32:17 -0700308 def write_crash_dir_entry(self, name, contents):
Simon Glassa47f0d72011-03-15 11:45:32 -0700309 """Writes an empty file to the system crash directory.
310
311 This writes a file to _SYSTEM_CRASH_DIR with the given name. This is
312 used to insert new crash dump files for testing purposes.
313
314 Args:
315 name: Name of file to write.
316 contents: String to write to the file.
317 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700318 entry = os.path.join(self._SYSTEM_CRASH_DIR, name)
319 if not os.path.exists(self._SYSTEM_CRASH_DIR):
320 os.makedirs(self._SYSTEM_CRASH_DIR)
Ken Mixter67ff5622010-09-30 15:32:17 -0700321 utils.open_write_close(entry, contents)
Ken Mixter20d9e472010-08-12 10:58:46 -0700322 return entry
323
324
Ken Mixterdee4e292010-12-14 17:45:21 -0800325 def write_fake_meta(self, name, exec_name, payload, log=None,
326 complete=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700327 """Writes a fake meta entry to the system crash directory.
328
329 Args:
330 name: Name of file to write.
331 exec_name: Value for exec_name item.
332 payload: Value for payload item.
333 log: Value for log item.
334 complete: True to close off the record, otherwise leave it
335 incomplete.
336 """
Ken Mixter1a894e02010-10-28 15:42:52 -0700337 last_line = ''
338 if complete:
339 last_line = 'done=1\n'
Ken Mixterdee4e292010-12-14 17:45:21 -0800340 contents = ('exec_name=%s\n'
341 'ver=my_ver\n'
342 'payload=%s\n'
343 '%s' % (exec_name, payload,
344 last_line))
345 if log:
346 contents = ('log=%s\n' % log) + contents
347 return self.write_crash_dir_entry(name, contents)
Ken Mixter67ff5622010-09-30 15:32:17 -0700348
349
Ken Mixter20d9e472010-08-12 10:58:46 -0700350 def _prepare_sender_one_crash(self,
351 send_success,
352 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700353 report):
Simon Glassa47f0d72011-03-15 11:45:32 -0700354 """Create metadata for a fake crash report.
355
356 This enabled mocking of the crash sender, then creates a fake
357 crash report for testing purposes.
358
359 Args:
360 send_success: True to make the crash_sender success, False to make
361 it fail.
362 reports_enabled: True to enable consent to that reports will be
363 sent.
364 report: Report to use for crash, if None we create one.
365 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700366 self._set_sending_mock(mock_enabled=True, send_success=send_success)
367 self._set_consent(reports_enabled)
Ken Mixter38dfe852010-08-18 15:24:00 -0700368 if report is None:
Ken Mixter1a894e02010-10-28 15:42:52 -0700369 payload = self.write_crash_dir_entry('fake.dmp', '')
370 report = self.write_fake_meta('fake.meta', 'fake', payload)
Ken Mixter38dfe852010-08-18 15:24:00 -0700371 return report
Ken Mixter20d9e472010-08-12 10:58:46 -0700372
373
374 def _parse_sender_output(self, output):
375 """Parse the log output from the crash_sender script.
376
377 This script can run on the logs from either a mocked or true
378 crash send.
379
380 Args:
381 output: output from the script
382
383 Returns:
384 A dictionary with these values:
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700385 error_type: an error type, if given
Ken Mixter38dfe852010-08-18 15:24:00 -0700386 exec_name: name of executable which crashed
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700387 image_type: type of image ("dev","force-official",...), if given
Ken Mixter67ff5622010-09-30 15:32:17 -0700388 meta_path: path to the report metadata file
389 output: the output from the script, copied
Ken Mixter38dfe852010-08-18 15:24:00 -0700390 report_kind: kind of report sent (minidump vs kernel)
Ken Mixter20d9e472010-08-12 10:58:46 -0700391 send_attempt: did the script attempt to send a crash.
392 send_success: if it attempted, was the crash send successful.
Ken Mixterd79140e2010-10-26 14:45:30 -0700393 sig: signature of the report, if given.
Ken Mixter20d9e472010-08-12 10:58:46 -0700394 sleep_time: if it attempted, how long did it sleep before
395 sending (if mocked, how long would it have slept)
Ken Mixter20d9e472010-08-12 10:58:46 -0700396 """
397 sleep_match = re.search('Scheduled to send in (\d+)s', output)
398 send_attempt = sleep_match is not None
399 if send_attempt:
400 sleep_time = int(sleep_match.group(1))
401 else:
402 sleep_time = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700403
Ken Mixter67ff5622010-09-30 15:32:17 -0700404 meta_match = re.search('Metadata: (\S+) \((\S+)\)', output)
405 if meta_match:
406 meta_path = meta_match.group(1)
407 report_kind = meta_match.group(2)
Ken Mixter38dfe852010-08-18 15:24:00 -0700408 else:
Ken Mixter67ff5622010-09-30 15:32:17 -0700409 meta_path = None
Ken Mixter38dfe852010-08-18 15:24:00 -0700410 report_kind = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700411
Ken Mixter67ff5622010-09-30 15:32:17 -0700412 payload_match = re.search('Payload: (\S+)', output)
413 if payload_match:
414 report_payload = payload_match.group(1)
415 else:
416 report_payload = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700417
Ken Mixter38dfe852010-08-18 15:24:00 -0700418 exec_name_match = re.search('Exec name: (\S+)', output)
419 if exec_name_match:
420 exec_name = exec_name_match.group(1)
421 else:
422 exec_name = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700423
Ken Mixter10c48672010-11-01 13:37:08 -0700424 sig_match = re.search('sig: (\S+)', output)
Ken Mixterd79140e2010-10-26 14:45:30 -0700425 if sig_match:
426 sig = sig_match.group(1)
427 else:
428 sig = None
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700429
430 error_type_match = re.search('Error type: (\S+)', output)
431 if error_type_match:
432 error_type = error_type_match.group(1)
433 else:
434 error_type = None
435
436 image_type_match = re.search('Image type: (\S+)', output)
437 if image_type_match:
438 image_type = image_type_match.group(1)
439 else:
440 image_type = None
441
Ken Mixter20d9e472010-08-12 10:58:46 -0700442 send_success = 'Mocking successful send' in output
Ken Mixter38dfe852010-08-18 15:24:00 -0700443 return {'exec_name': exec_name,
444 'report_kind': report_kind,
Ken Mixter67ff5622010-09-30 15:32:17 -0700445 'meta_path': meta_path,
446 'report_payload': report_payload,
Ken Mixter38dfe852010-08-18 15:24:00 -0700447 'send_attempt': send_attempt,
Ken Mixter20d9e472010-08-12 10:58:46 -0700448 'send_success': send_success,
Ken Mixterd79140e2010-10-26 14:45:30 -0700449 'sig': sig,
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700450 'error_type': error_type,
451 'image_type': image_type,
Ken Mixter20d9e472010-08-12 10:58:46 -0700452 'sleep_time': sleep_time,
453 'output': output}
454
455
Ken Mixter654f32e2010-10-20 11:47:31 -0700456 def wait_for_sender_completion(self):
457 """Wait for crash_sender to complete.
458
459 Wait for no crash_sender's last message to be placed in the
460 system log before continuing and for the process to finish.
461 Otherwise we might get only part of the output."""
Eric Lie7c4cab2011-01-05 14:39:19 -0800462 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700463 lambda: self._log_reader.can_find('crash_sender done.'),
464 timeout=60,
465 exception=error.TestError(
466 'Timeout waiting for crash_sender to emit done: ' +
467 self._log_reader.get_logs()))
Eric Lie7c4cab2011-01-05 14:39:19 -0800468 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700469 lambda: utils.system('pgrep crash_sender',
470 ignore_status=True) != 0,
471 timeout=60,
472 exception=error.TestError(
473 'Timeout waiting for crash_sender to finish: ' +
474 self._log_reader.get_logs()))
475
476
Ken Mixter20d9e472010-08-12 10:58:46 -0700477 def _call_sender_one_crash(self,
478 send_success=True,
479 reports_enabled=True,
480 username='root',
Ken Mixter38dfe852010-08-18 15:24:00 -0700481 report=None):
Ken Mixter20d9e472010-08-12 10:58:46 -0700482 """Call the crash sender script to mock upload one crash.
483
484 Args:
485 send_success: Mock a successful send if true
486 reports_enabled: Has the user consented to sending crash reports.
487 username: user to emulate a crash from
Ken Mixter38dfe852010-08-18 15:24:00 -0700488 report: report to use for crash, if None we create one.
Ken Mixter20d9e472010-08-12 10:58:46 -0700489
490 Returns:
491 Returns a dictionary describing the result with the keys
492 from _parse_sender_output, as well as:
Ken Mixter38dfe852010-08-18 15:24:00 -0700493 report_exists: does the minidump still exist after calling
Ken Mixter20d9e472010-08-12 10:58:46 -0700494 send script
495 rate_count: how many crashes have been uploaded in the past
496 24 hours.
497 """
Ken Mixter38dfe852010-08-18 15:24:00 -0700498 report = self._prepare_sender_one_crash(send_success,
499 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700500 report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700501 self._log_reader.set_start_by_current()
502 script_output = utils.system_output(
503 '/bin/sh -c "%s" 2>&1' % self._CRASH_SENDER_PATH,
504 ignore_status=True)
Ken Mixter654f32e2010-10-20 11:47:31 -0700505 self.wait_for_sender_completion()
Ken Mixter20d9e472010-08-12 10:58:46 -0700506 output = self._log_reader.get_logs()
507 logging.debug('Crash sender message output:\n' + output)
508 if script_output != '':
509 raise error.TestFail(
510 'Unexpected crash_sender stdout/stderr: ' + script_output)
511
Ken Mixter38dfe852010-08-18 15:24:00 -0700512 if os.path.exists(report):
513 report_exists = True
514 os.remove(report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700515 else:
Ken Mixter38dfe852010-08-18 15:24:00 -0700516 report_exists = False
Ken Mixter20d9e472010-08-12 10:58:46 -0700517 if os.path.exists(self._CRASH_SENDER_RATE_DIR):
518 rate_count = len(os.listdir(self._CRASH_SENDER_RATE_DIR))
519 else:
520 rate_count = 0
521
522 result = self._parse_sender_output(output)
Ken Mixter38dfe852010-08-18 15:24:00 -0700523 result['report_exists'] = report_exists
Ken Mixter20d9e472010-08-12 10:58:46 -0700524 result['rate_count'] = rate_count
525
526 # Show the result for debugging but remove 'output' key
527 # since it's large and earlier in debug output.
528 debug_result = dict(result)
529 del debug_result['output']
530 logging.debug('Result of send (besides output): %s' % debug_result)
531
532 return result
533
534
Ken Mixterddcd92d2010-11-01 19:07:08 -0700535 def _replace_crash_reporter_filter_in(self, new_parameter):
Simon Glassa47f0d72011-03-15 11:45:32 -0700536 """Replaces the --filter_in= parameter of the crash reporter.
537
538 The kernel is set up to call the crash reporter with the core dump
539 as stdin when a process dies. This function adds a filter to the
540 command line used to call the crash reporter. This is used to ignore
541 crashes in which we have no interest.
542
543 This removes any --filter_in= parameter and optionally replaces it
544 with a new one.
545
546 Args:
547 new_parameter: This is parameter to add to the command line
548 instead of the --filter_in=... that was there.
549 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700550 core_pattern = utils.read_file(self._CORE_PATTERN)[:-1]
551 core_pattern = re.sub('--filter_in=\S*\s*', '',
552 core_pattern).rstrip()
553 if new_parameter:
554 core_pattern += ' ' + new_parameter
555 utils.system('echo "%s" > %s' % (core_pattern, self._CORE_PATTERN))
556
557
558 def enable_crash_filtering(self, name):
Simon Glassa47f0d72011-03-15 11:45:32 -0700559 """Add a --filter_in argument to the kernel core dump cmdline.
560
561 Args:
562 name: Filter text to use. This is passed as a --filter_in
563 argument to the crash reporter.
564 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700565 self._replace_crash_reporter_filter_in('--filter_in=' + name)
566
567
568 def disable_crash_filtering(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700569 """Remove the --filter_in argument from the kernel core dump cmdline.
570
571 Next time the crash reporter is invoked (due to a crash) it will not
572 receive a --filter_in paramter."""
Ken Mixterddcd92d2010-11-01 19:07:08 -0700573 self._replace_crash_reporter_filter_in('')
574
575
Ken Mixter20d9e472010-08-12 10:58:46 -0700576 def initialize(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700577 """Initalize the test."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700578 test.test.initialize(self)
Eric Lie7c4cab2011-01-05 14:39:19 -0800579 self._log_reader = cros_logging.LogReader()
Ken Mixter38dfe852010-08-18 15:24:00 -0700580 self._leave_crash_sending = True
Ken Mixter67ff5622010-09-30 15:32:17 -0700581 self._automatic_consent_saving = True
Ken Mixterddcd92d2010-11-01 19:07:08 -0700582 self.enable_crash_filtering('none')
Thieu Lec16253b2011-03-03 11:13:54 -0800583 self._set_crash_test_in_progress(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700584
585
586 def cleanup(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700587 """Cleanup after the test.
588
589 We reset things back to the way we think they should be. This is
590 intended to allow the system to continue normal operation.
591
592 Some variables silently change the behavior:
593 _automatic_consent_saving: if True, we pop the consent file.
594 _leave_crash_sending: True to enable crash sending, False to
595 disable it
596 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700597 self._reset_rate_limiting()
598 self._clear_spooled_crashes()
Ken Mixter4f619652010-10-18 12:11:18 -0700599 self._set_system_sending(self._leave_crash_sending)
Ken Mixter20d9e472010-08-12 10:58:46 -0700600 self._set_sending_mock(mock_enabled=False)
Ken Mixter67ff5622010-09-30 15:32:17 -0700601 if self._automatic_consent_saving:
602 self._pop_consent()
Ken Mixterddcd92d2010-11-01 19:07:08 -0700603 self.disable_crash_filtering()
Thieu Lec16253b2011-03-03 11:13:54 -0800604 self._set_crash_test_in_progress(False)
Ken Mixter20d9e472010-08-12 10:58:46 -0700605 test.test.cleanup(self)
606
607
Ken Mixter38dfe852010-08-18 15:24:00 -0700608 def run_crash_tests(self,
609 test_names,
610 initialize_crash_reporter=False,
611 clear_spool_first=True,
612 must_run_all=True):
613 """Run crash tests defined in this class.
614
615 Args:
Simon Glassa47f0d72011-03-15 11:45:32 -0700616 test_names: Array of test names.
617 initialize_crash_reporter: Should set up crash reporter for every
618 run.
619 clear_spool_first: Clear all spooled user/system crashes before
620 starting the test.
621 must_run_all: Should make sure every test in this class is
622 mentioned in test_names.
Ken Mixter38dfe852010-08-18 15:24:00 -0700623 """
Ken Mixter67ff5622010-09-30 15:32:17 -0700624 if self._automatic_consent_saving:
625 self._push_consent()
Ken Mixter20d9e472010-08-12 10:58:46 -0700626
Ken Mixter38dfe852010-08-18 15:24:00 -0700627 if must_run_all:
628 # Sanity check test_names is complete
629 for attr in dir(self):
630 if attr.find('_test_') == 0:
631 test_name = attr[6:]
632 if not test_name in test_names:
633 raise error.TestError('Test %s is missing' % test_name)
Ken Mixter20d9e472010-08-12 10:58:46 -0700634
635 for test_name in test_names:
636 logging.info(('=' * 20) + ('Running %s' % test_name) + ('=' * 20))
Ken Mixter38dfe852010-08-18 15:24:00 -0700637 if initialize_crash_reporter:
638 self._initialize_crash_reporter()
Ken Mixter4f619652010-10-18 12:11:18 -0700639 # Disable crash_sender from running, kill off any running ones, but
640 # set environment so crash_sender may run as a child process.
641 self._set_system_sending(False)
642 self._set_child_sending(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700643 self._kill_running_sender()
644 self._reset_rate_limiting()
Michael Krebs6cffa3d2012-09-06 20:09:11 -0700645 # Default to not overriding for unofficial versions.
646 self._set_force_official(False)
Ken Mixter38dfe852010-08-18 15:24:00 -0700647 if clear_spool_first:
648 self._clear_spooled_crashes()
Simon Glassa47f0d72011-03-15 11:45:32 -0700649
650 # Call the test function
Ken Mixter20d9e472010-08-12 10:58:46 -0700651 getattr(self, '_test_' + test_name)()