blob: d307b93c6a06e80fb61a4ae609c92d6200697e23 [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
Ken Mixter20d9e472010-08-12 10:58:46 -0700118 def _reset_rate_limiting(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700119 """Reset the count of crash reports sent today.
120
121 This clears the contents of the rate limiting directory which has
122 the effect of reseting our count of crash reports sent.
123 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700124 utils.system('rm -rf ' + self._CRASH_SENDER_RATE_DIR)
125
126
127 def _clear_spooled_crashes(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700128 """Clears system and user crash directories.
129
130 This will remove all crash reports which are waiting to be sent.
131 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700132 utils.system('rm -rf ' + self._SYSTEM_CRASH_DIR)
133 utils.system('rm -rf ' + self._USER_CRASH_DIR)
134
135
136 def _kill_running_sender(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700137 """Kill the the crash_sender process if running.
138
139 We use the PID file to find the process ID, then kill it with signal 9.
140 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700141 if not os.path.exists(self._CRASH_SENDER_RUN_PATH):
142 return
143 running_pid = int(utils.read_file(self._CRASH_SENDER_RUN_PATH))
144 logging.warning('Detected running crash sender (%d), killing' %
145 running_pid)
146 utils.system('kill -9 %d' % running_pid)
147 os.remove(self._CRASH_SENDER_RUN_PATH)
148
149
150 def _set_sending_mock(self, mock_enabled, send_success=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700151 """Enables / disables mocking of the sending process.
152
153 This uses the _MOCK_CRASH_SENDING file to achieve its aims. See notes
154 at the top.
155
156 Args:
157 mock_enabled: If True, mocking is enabled, else it is disabled.
158 send_success: If mock_enabled this is True for the mocking to
159 indicate success, False to indicate failure.
160 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700161 if mock_enabled:
162 if send_success:
163 data = ''
164 else:
165 data = '1'
166 logging.info('Setting sending mock')
167 utils.open_write_close(self._MOCK_CRASH_SENDING, data)
168 else:
169 utils.system('rm -f ' + self._MOCK_CRASH_SENDING)
170
171
172 def _set_consent(self, has_consent):
Simon Glassa47f0d72011-03-15 11:45:32 -0700173 """Sets whether or not we have consent to send crash reports.
174
175 This creates or deletes the _CONSENT_FILE to control whether
176 crash_sender will consider that it has consent to send crash reports.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200177 It also copies a policy blob with the proper policy setting.
Simon Glassa47f0d72011-03-15 11:45:32 -0700178
179 Args:
180 has_consent: True to indicate consent, False otherwise
181 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700182 if has_consent:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700183 # Create policy file that enables metrics/consent.
184 shutil.copy('/usr/local/autotest/cros/mock_metrics_on.policy',
185 self._POLICY_FILE)
186 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
187 self._OWNER_KEY_FILE)
188 # Create deprecated consent file. This is created *after* the
189 # policy file in order to avoid a race condition where chrome
190 # might remove the consent file if the policy's not set yet.
Michael Krebse9028fc2011-08-19 15:00:00 -0700191 # We create it as a temp file first in order to make the creation
192 # of the consent file, owned by chronos, atomic.
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700193 # See crosbug.com/18413.
Michael Krebse9028fc2011-08-19 15:00:00 -0700194 temp_file = self._CONSENT_FILE + '.tmp';
195 utils.open_write_close(temp_file, 'test-consent')
196 utils.system('chown chronos:chronos "%s"' % (temp_file))
197 shutil.move(temp_file, self._CONSENT_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700198 logging.info('Created ' + self._CONSENT_FILE)
199 else:
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700200 # Create policy file that disables metrics/consent.
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200201 shutil.copy('/usr/local/autotest/cros/mock_metrics_off.policy',
202 self._POLICY_FILE)
Michael Krebsb4b6f6b2011-08-03 13:52:19 -0700203 shutil.copy('/usr/local/autotest/cros/mock_metrics_owner.key',
204 self._OWNER_KEY_FILE)
205 # Remove deprecated consent file.
206 utils.system('rm -f "%s"' % (self._CONSENT_FILE))
Ken Mixter20d9e472010-08-12 10:58:46 -0700207
208
Thieu Lec16253b2011-03-03 11:13:54 -0800209 def _set_crash_test_in_progress(self, in_progress):
210 if in_progress:
211 utils.open_write_close(self._CRASH_TEST_IN_PROGRESS, 'in-progress')
212 logging.info('Created ' + self._CRASH_TEST_IN_PROGRESS)
213 else:
214 utils.system('rm -f "%s"' % (self._CRASH_TEST_IN_PROGRESS))
215
216
Ken Mixter20d9e472010-08-12 10:58:46 -0700217 def _get_pushed_consent_file_path(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700218 """Returns filename of the pushed consent file."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700219 return os.path.join(self.bindir, 'pushed_consent')
220
221
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200222 def _get_pushed_policy_file_path(self):
223 """Returns filename of the pushed policy file."""
224 return os.path.join(self.bindir, 'pushed_policy')
225
226
227 def _get_pushed_owner_key_file_path(self):
228 """Returns filename of the pushed owner.key file."""
229 return os.path.join(self.bindir, 'pushed_owner_key')
230
231
Ken Mixter20d9e472010-08-12 10:58:46 -0700232 def _push_consent(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700233 """Push the consent file, thus disabling consent.
234
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200235 The consent files can be created in the new test if required. Call
Simon Glassa47f0d72011-03-15 11:45:32 -0700236 _pop_consent() to restore the original state.
237 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700238 if os.path.exists(self._CONSENT_FILE):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800239 shutil.move(self._CONSENT_FILE,
240 self._get_pushed_consent_file_path())
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200241 if os.path.exists(self._POLICY_FILE):
242 shutil.move(self._POLICY_FILE,
243 self._get_pushed_policy_file_path())
244 if os.path.exists(self._OWNER_KEY_FILE):
245 shutil.move(self._OWNER_KEY_FILE,
246 self._get_pushed_owner_key_file_path())
Ken Mixter20d9e472010-08-12 10:58:46 -0700247
248
249 def _pop_consent(self):
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200250 """Pop the consent files, enabling/disabling consent as it was before
Simon Glassa47f0d72011-03-15 11:45:32 -0700251 we pushed the consent."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700252 if os.path.exists(self._get_pushed_consent_file_path()):
Dale Curtis497c2cb2010-11-16 13:44:33 -0800253 shutil.move(self._get_pushed_consent_file_path(),
254 self._CONSENT_FILE)
Julian Pastarmovd56badb2011-07-15 20:24:45 +0200255 else:
256 utils.system('rm -f "%s"' % self._CONSENT_FILE)
257 if os.path.exists(self._get_pushed_policy_file_path()):
258 shutil.move(self._get_pushed_policy_file_path(),
259 self._POLICY_FILE)
260 else:
261 utils.system('rm -f "%s"' % self._POLICY_FILE)
262 if os.path.exists(self._get_pushed_owner_key_file_path()):
263 shutil.move(self._get_pushed_owner_key_file_path(),
264 self._OWNER_KEY_FILE)
265 else:
266 utils.system('rm -f "%s"' % self._OWNER_KEY_FILE)
Ken Mixter20d9e472010-08-12 10:58:46 -0700267
268
269 def _get_crash_dir(self, username):
Simon Glassa47f0d72011-03-15 11:45:32 -0700270 """Returns full path to the crash directory for a given username
271
272 Args:
273 username: username to use:
274 'chronos': Returns user crash directory.
275 'root': Returns system crash directory.
276 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700277 if username == 'chronos':
278 return self._USER_CRASH_DIR
279 else:
280 return self._SYSTEM_CRASH_DIR
281
282
283 def _initialize_crash_reporter(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700284 """Start up the crash reporter."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700285 utils.system('%s --init --nounclean_check' % self._CRASH_REPORTER_PATH)
Ken Mixterddcd92d2010-11-01 19:07:08 -0700286 # Completely disable crash_reporter from generating crash dumps
287 # while any tests are running, otherwise a crashy system can make
288 # these tests flaky.
289 self.enable_crash_filtering('none')
Ken Mixter20d9e472010-08-12 10:58:46 -0700290
291
Ken Mixter67ff5622010-09-30 15:32:17 -0700292 def write_crash_dir_entry(self, name, contents):
Simon Glassa47f0d72011-03-15 11:45:32 -0700293 """Writes an empty file to the system crash directory.
294
295 This writes a file to _SYSTEM_CRASH_DIR with the given name. This is
296 used to insert new crash dump files for testing purposes.
297
298 Args:
299 name: Name of file to write.
300 contents: String to write to the file.
301 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700302 entry = os.path.join(self._SYSTEM_CRASH_DIR, name)
303 if not os.path.exists(self._SYSTEM_CRASH_DIR):
304 os.makedirs(self._SYSTEM_CRASH_DIR)
Ken Mixter67ff5622010-09-30 15:32:17 -0700305 utils.open_write_close(entry, contents)
Ken Mixter20d9e472010-08-12 10:58:46 -0700306 return entry
307
308
Ken Mixterdee4e292010-12-14 17:45:21 -0800309 def write_fake_meta(self, name, exec_name, payload, log=None,
310 complete=True):
Simon Glassa47f0d72011-03-15 11:45:32 -0700311 """Writes a fake meta entry to the system crash directory.
312
313 Args:
314 name: Name of file to write.
315 exec_name: Value for exec_name item.
316 payload: Value for payload item.
317 log: Value for log item.
318 complete: True to close off the record, otherwise leave it
319 incomplete.
320 """
Ken Mixter1a894e02010-10-28 15:42:52 -0700321 last_line = ''
322 if complete:
323 last_line = 'done=1\n'
Ken Mixterdee4e292010-12-14 17:45:21 -0800324 contents = ('exec_name=%s\n'
325 'ver=my_ver\n'
326 'payload=%s\n'
327 '%s' % (exec_name, payload,
328 last_line))
329 if log:
330 contents = ('log=%s\n' % log) + contents
331 return self.write_crash_dir_entry(name, contents)
Ken Mixter67ff5622010-09-30 15:32:17 -0700332
333
Ken Mixter20d9e472010-08-12 10:58:46 -0700334 def _prepare_sender_one_crash(self,
335 send_success,
336 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700337 report):
Simon Glassa47f0d72011-03-15 11:45:32 -0700338 """Create metadata for a fake crash report.
339
340 This enabled mocking of the crash sender, then creates a fake
341 crash report for testing purposes.
342
343 Args:
344 send_success: True to make the crash_sender success, False to make
345 it fail.
346 reports_enabled: True to enable consent to that reports will be
347 sent.
348 report: Report to use for crash, if None we create one.
349 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700350 self._set_sending_mock(mock_enabled=True, send_success=send_success)
351 self._set_consent(reports_enabled)
Ken Mixter38dfe852010-08-18 15:24:00 -0700352 if report is None:
Ken Mixter1a894e02010-10-28 15:42:52 -0700353 payload = self.write_crash_dir_entry('fake.dmp', '')
354 report = self.write_fake_meta('fake.meta', 'fake', payload)
Ken Mixter38dfe852010-08-18 15:24:00 -0700355 return report
Ken Mixter20d9e472010-08-12 10:58:46 -0700356
357
358 def _parse_sender_output(self, output):
359 """Parse the log output from the crash_sender script.
360
361 This script can run on the logs from either a mocked or true
362 crash send.
363
364 Args:
365 output: output from the script
366
367 Returns:
368 A dictionary with these values:
Ken Mixter38dfe852010-08-18 15:24:00 -0700369 exec_name: name of executable which crashed
Ken Mixter67ff5622010-09-30 15:32:17 -0700370 meta_path: path to the report metadata file
371 output: the output from the script, copied
Ken Mixter38dfe852010-08-18 15:24:00 -0700372 report_kind: kind of report sent (minidump vs kernel)
Ken Mixter20d9e472010-08-12 10:58:46 -0700373 send_attempt: did the script attempt to send a crash.
374 send_success: if it attempted, was the crash send successful.
Ken Mixterd79140e2010-10-26 14:45:30 -0700375 sig: signature of the report, if given.
Ken Mixter20d9e472010-08-12 10:58:46 -0700376 sleep_time: if it attempted, how long did it sleep before
377 sending (if mocked, how long would it have slept)
Ken Mixter20d9e472010-08-12 10:58:46 -0700378 """
379 sleep_match = re.search('Scheduled to send in (\d+)s', output)
380 send_attempt = sleep_match is not None
381 if send_attempt:
382 sleep_time = int(sleep_match.group(1))
383 else:
384 sleep_time = None
Ken Mixter67ff5622010-09-30 15:32:17 -0700385 meta_match = re.search('Metadata: (\S+) \((\S+)\)', output)
386 if meta_match:
387 meta_path = meta_match.group(1)
388 report_kind = meta_match.group(2)
Ken Mixter38dfe852010-08-18 15:24:00 -0700389 else:
Ken Mixter67ff5622010-09-30 15:32:17 -0700390 meta_path = None
Ken Mixter38dfe852010-08-18 15:24:00 -0700391 report_kind = None
Ken Mixter67ff5622010-09-30 15:32:17 -0700392 payload_match = re.search('Payload: (\S+)', output)
393 if payload_match:
394 report_payload = payload_match.group(1)
395 else:
396 report_payload = None
Ken Mixter38dfe852010-08-18 15:24:00 -0700397 exec_name_match = re.search('Exec name: (\S+)', output)
398 if exec_name_match:
399 exec_name = exec_name_match.group(1)
400 else:
401 exec_name = None
Ken Mixter10c48672010-11-01 13:37:08 -0700402 sig_match = re.search('sig: (\S+)', output)
Ken Mixterd79140e2010-10-26 14:45:30 -0700403 if sig_match:
404 sig = sig_match.group(1)
405 else:
406 sig = None
Ken Mixter20d9e472010-08-12 10:58:46 -0700407 send_success = 'Mocking successful send' in output
Ken Mixter38dfe852010-08-18 15:24:00 -0700408 return {'exec_name': exec_name,
409 'report_kind': report_kind,
Ken Mixter67ff5622010-09-30 15:32:17 -0700410 'meta_path': meta_path,
411 'report_payload': report_payload,
Ken Mixter38dfe852010-08-18 15:24:00 -0700412 'send_attempt': send_attempt,
Ken Mixter20d9e472010-08-12 10:58:46 -0700413 'send_success': send_success,
Ken Mixterd79140e2010-10-26 14:45:30 -0700414 'sig': sig,
Ken Mixter20d9e472010-08-12 10:58:46 -0700415 'sleep_time': sleep_time,
416 'output': output}
417
418
Ken Mixter654f32e2010-10-20 11:47:31 -0700419 def wait_for_sender_completion(self):
420 """Wait for crash_sender to complete.
421
422 Wait for no crash_sender's last message to be placed in the
423 system log before continuing and for the process to finish.
424 Otherwise we might get only part of the output."""
Eric Lie7c4cab2011-01-05 14:39:19 -0800425 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700426 lambda: self._log_reader.can_find('crash_sender done.'),
427 timeout=60,
428 exception=error.TestError(
429 'Timeout waiting for crash_sender to emit done: ' +
430 self._log_reader.get_logs()))
Eric Lie7c4cab2011-01-05 14:39:19 -0800431 utils.poll_for_condition(
Ken Mixter654f32e2010-10-20 11:47:31 -0700432 lambda: utils.system('pgrep crash_sender',
433 ignore_status=True) != 0,
434 timeout=60,
435 exception=error.TestError(
436 'Timeout waiting for crash_sender to finish: ' +
437 self._log_reader.get_logs()))
438
439
Ken Mixter20d9e472010-08-12 10:58:46 -0700440 def _call_sender_one_crash(self,
441 send_success=True,
442 reports_enabled=True,
443 username='root',
Ken Mixter38dfe852010-08-18 15:24:00 -0700444 report=None):
Ken Mixter20d9e472010-08-12 10:58:46 -0700445 """Call the crash sender script to mock upload one crash.
446
447 Args:
448 send_success: Mock a successful send if true
449 reports_enabled: Has the user consented to sending crash reports.
450 username: user to emulate a crash from
Ken Mixter38dfe852010-08-18 15:24:00 -0700451 report: report to use for crash, if None we create one.
Ken Mixter20d9e472010-08-12 10:58:46 -0700452
453 Returns:
454 Returns a dictionary describing the result with the keys
455 from _parse_sender_output, as well as:
Ken Mixter38dfe852010-08-18 15:24:00 -0700456 report_exists: does the minidump still exist after calling
Ken Mixter20d9e472010-08-12 10:58:46 -0700457 send script
458 rate_count: how many crashes have been uploaded in the past
459 24 hours.
460 """
Ken Mixter38dfe852010-08-18 15:24:00 -0700461 report = self._prepare_sender_one_crash(send_success,
462 reports_enabled,
Ken Mixter38dfe852010-08-18 15:24:00 -0700463 report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700464 self._log_reader.set_start_by_current()
465 script_output = utils.system_output(
466 '/bin/sh -c "%s" 2>&1' % self._CRASH_SENDER_PATH,
467 ignore_status=True)
Ken Mixter654f32e2010-10-20 11:47:31 -0700468 self.wait_for_sender_completion()
Ken Mixter20d9e472010-08-12 10:58:46 -0700469 output = self._log_reader.get_logs()
470 logging.debug('Crash sender message output:\n' + output)
471 if script_output != '':
472 raise error.TestFail(
473 'Unexpected crash_sender stdout/stderr: ' + script_output)
474
Ken Mixter38dfe852010-08-18 15:24:00 -0700475 if os.path.exists(report):
476 report_exists = True
477 os.remove(report)
Ken Mixter20d9e472010-08-12 10:58:46 -0700478 else:
Ken Mixter38dfe852010-08-18 15:24:00 -0700479 report_exists = False
Ken Mixter20d9e472010-08-12 10:58:46 -0700480 if os.path.exists(self._CRASH_SENDER_RATE_DIR):
481 rate_count = len(os.listdir(self._CRASH_SENDER_RATE_DIR))
482 else:
483 rate_count = 0
484
485 result = self._parse_sender_output(output)
Ken Mixter38dfe852010-08-18 15:24:00 -0700486 result['report_exists'] = report_exists
Ken Mixter20d9e472010-08-12 10:58:46 -0700487 result['rate_count'] = rate_count
488
489 # Show the result for debugging but remove 'output' key
490 # since it's large and earlier in debug output.
491 debug_result = dict(result)
492 del debug_result['output']
493 logging.debug('Result of send (besides output): %s' % debug_result)
494
495 return result
496
497
Ken Mixterddcd92d2010-11-01 19:07:08 -0700498 def _replace_crash_reporter_filter_in(self, new_parameter):
Simon Glassa47f0d72011-03-15 11:45:32 -0700499 """Replaces the --filter_in= parameter of the crash reporter.
500
501 The kernel is set up to call the crash reporter with the core dump
502 as stdin when a process dies. This function adds a filter to the
503 command line used to call the crash reporter. This is used to ignore
504 crashes in which we have no interest.
505
506 This removes any --filter_in= parameter and optionally replaces it
507 with a new one.
508
509 Args:
510 new_parameter: This is parameter to add to the command line
511 instead of the --filter_in=... that was there.
512 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700513 core_pattern = utils.read_file(self._CORE_PATTERN)[:-1]
514 core_pattern = re.sub('--filter_in=\S*\s*', '',
515 core_pattern).rstrip()
516 if new_parameter:
517 core_pattern += ' ' + new_parameter
518 utils.system('echo "%s" > %s' % (core_pattern, self._CORE_PATTERN))
519
520
521 def enable_crash_filtering(self, name):
Simon Glassa47f0d72011-03-15 11:45:32 -0700522 """Add a --filter_in argument to the kernel core dump cmdline.
523
524 Args:
525 name: Filter text to use. This is passed as a --filter_in
526 argument to the crash reporter.
527 """
Ken Mixterddcd92d2010-11-01 19:07:08 -0700528 self._replace_crash_reporter_filter_in('--filter_in=' + name)
529
530
531 def disable_crash_filtering(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700532 """Remove the --filter_in argument from the kernel core dump cmdline.
533
534 Next time the crash reporter is invoked (due to a crash) it will not
535 receive a --filter_in paramter."""
Ken Mixterddcd92d2010-11-01 19:07:08 -0700536 self._replace_crash_reporter_filter_in('')
537
538
Ken Mixter20d9e472010-08-12 10:58:46 -0700539 def initialize(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700540 """Initalize the test."""
Ken Mixter20d9e472010-08-12 10:58:46 -0700541 test.test.initialize(self)
Eric Lie7c4cab2011-01-05 14:39:19 -0800542 self._log_reader = cros_logging.LogReader()
Ken Mixter38dfe852010-08-18 15:24:00 -0700543 self._leave_crash_sending = True
Ken Mixter67ff5622010-09-30 15:32:17 -0700544 self._automatic_consent_saving = True
Ken Mixterddcd92d2010-11-01 19:07:08 -0700545 self.enable_crash_filtering('none')
Thieu Lec16253b2011-03-03 11:13:54 -0800546 self._set_crash_test_in_progress(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700547
548
549 def cleanup(self):
Simon Glassa47f0d72011-03-15 11:45:32 -0700550 """Cleanup after the test.
551
552 We reset things back to the way we think they should be. This is
553 intended to allow the system to continue normal operation.
554
555 Some variables silently change the behavior:
556 _automatic_consent_saving: if True, we pop the consent file.
557 _leave_crash_sending: True to enable crash sending, False to
558 disable it
559 """
Ken Mixter20d9e472010-08-12 10:58:46 -0700560 self._reset_rate_limiting()
561 self._clear_spooled_crashes()
Ken Mixter4f619652010-10-18 12:11:18 -0700562 self._set_system_sending(self._leave_crash_sending)
Ken Mixter20d9e472010-08-12 10:58:46 -0700563 self._set_sending_mock(mock_enabled=False)
Ken Mixter67ff5622010-09-30 15:32:17 -0700564 if self._automatic_consent_saving:
565 self._pop_consent()
Ken Mixterddcd92d2010-11-01 19:07:08 -0700566 self.disable_crash_filtering()
Thieu Lec16253b2011-03-03 11:13:54 -0800567 self._set_crash_test_in_progress(False)
Ken Mixter20d9e472010-08-12 10:58:46 -0700568 test.test.cleanup(self)
569
570
Ken Mixter38dfe852010-08-18 15:24:00 -0700571 def run_crash_tests(self,
572 test_names,
573 initialize_crash_reporter=False,
574 clear_spool_first=True,
575 must_run_all=True):
576 """Run crash tests defined in this class.
577
578 Args:
Simon Glassa47f0d72011-03-15 11:45:32 -0700579 test_names: Array of test names.
580 initialize_crash_reporter: Should set up crash reporter for every
581 run.
582 clear_spool_first: Clear all spooled user/system crashes before
583 starting the test.
584 must_run_all: Should make sure every test in this class is
585 mentioned in test_names.
Ken Mixter38dfe852010-08-18 15:24:00 -0700586 """
Ken Mixter67ff5622010-09-30 15:32:17 -0700587 if self._automatic_consent_saving:
588 self._push_consent()
Ken Mixter20d9e472010-08-12 10:58:46 -0700589
Ken Mixter38dfe852010-08-18 15:24:00 -0700590 if must_run_all:
591 # Sanity check test_names is complete
592 for attr in dir(self):
593 if attr.find('_test_') == 0:
594 test_name = attr[6:]
595 if not test_name in test_names:
596 raise error.TestError('Test %s is missing' % test_name)
Ken Mixter20d9e472010-08-12 10:58:46 -0700597
598 for test_name in test_names:
599 logging.info(('=' * 20) + ('Running %s' % test_name) + ('=' * 20))
Ken Mixter38dfe852010-08-18 15:24:00 -0700600 if initialize_crash_reporter:
601 self._initialize_crash_reporter()
Ken Mixter4f619652010-10-18 12:11:18 -0700602 # Disable crash_sender from running, kill off any running ones, but
603 # set environment so crash_sender may run as a child process.
604 self._set_system_sending(False)
605 self._set_child_sending(True)
Ken Mixter20d9e472010-08-12 10:58:46 -0700606 self._kill_running_sender()
607 self._reset_rate_limiting()
Ken Mixter38dfe852010-08-18 15:24:00 -0700608 if clear_spool_first:
609 self._clear_spooled_crashes()
Simon Glassa47f0d72011-03-15 11:45:32 -0700610
611 # Call the test function
Ken Mixter20d9e472010-08-12 10:58:46 -0700612 getattr(self, '_test_' + test_name)()