Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import logging, os, re, shutil | 5 import logging, os, re, shutil |
| 6 import common | 6 import common |
| 7 import cros_logging | 7 import cros_logging |
| 8 from autotest_lib.client.bin import test, utils | 8 from autotest_lib.client.bin import test, utils |
| 9 from autotest_lib.client.common_lib import error | 9 from autotest_lib.client.common_lib import error |
| 10 | 10 |
| 11 | 11 |
| 12 class CrashTest(test.test): | 12 class CrashTest(test.test): |
| 13 """ | |
| 14 This class deals with running crash tests, which are tests which crash the | |
| 15 machine and generate a core dump. We want to check that the correct crash | |
|
kmixter1
2011/02/25 00:15:15
Not necessarily the whole machine - both kernel or
| |
| 16 dump is available and can be retrieved. | |
| 17 | |
| 18 Chromium OS has a crash sender which checks for new crash data and sends | |
| 19 it to a server. This crash data is used to track software quality and find | |
| 20 bugs. The system crash sender normally is always running, but can be paused | |
| 21 by creating _PAUSE_FILE. When crash sender sees this, it pauses operation. | |
| 22 | |
| 23 The pid of the system crash sender is stored in _CRASH_SENDER_RUN_PATH so | |
| 24 we can use this to kill the system crash sender for when we want to run | |
| 25 our own. | |
| 26 | |
| 27 For testing purposes we sometimes want to run the crash sender manually. | |
| 28 In this case we can set 'OVERRIDE_PAUSE_SENDING=1' in the environment and | |
| 29 run the crash sender manually (as a child process). | |
| 30 | |
| 31 Also for testing we sometimes want to mock out the crash sender, and just | |
| 32 have it pretend to succeed or fail. The _MOCK_CRASH_SENDING file is used | |
| 33 for this. If it doesn't exist, then the crash sender runs normally. If | |
| 34 it exists but is empty, the crash sender will succeed (but actually do | |
| 35 nothing). If the file contains something, then the crash sender will fail. | |
| 36 | |
| 37 If the user consents to sending crash tests, then the _CONSENT_FILE will | |
| 38 exist in the home directory. This test needs to create this file for the | |
| 39 crash sending to work. | |
| 40 | |
| 41 Crash reports are rate limited to a certain number of reports each 24 | |
| 42 hours. If the maximum number has already been sent then reports are held | |
| 43 until later. This is administered by a directory _CRASH_SENDER_RATE_DIR | |
| 44 which contains one temporary file for each time a report is sent. | |
| 45 | |
| 46 The class provides the ability to push a consent file. This disables | |
| 47 consent for this test but allows it to be popped back at later. This | |
| 48 makes nested tests easier. If _automatic_consent_saving is True (the | |
| 49 default) then consent will be pushed at the start and popped at the end. | |
| 50 | |
| 51 Interesting variables: | |
| 52 _log_reader: the log reader used for reading log files | |
| 53 _leave_crash_sending: True to enable crash sending on exit from the | |
| 54 test, False to disable it. (Default True). | |
| 55 _automatic_consent_saving: True to push the consent at the start of | |
| 56 the test and pop it afterwards. (Default True). | |
| 57 | |
| 58 Useful places to look for more information are: | |
| 59 | |
| 60 chromeos/src/platform/crash-reporter/crash_sender | |
| 61 - sender script which crash crash reporter to create reports, then | |
| 62 | |
| 63 chromeos/src/platform/crash-reporter/ | |
| 64 - crash reporter program | |
| 65 """ | |
| 66 | |
| 13 | 67 |
| 14 _CONSENT_FILE = '/home/chronos/Consent To Send Stats' | 68 _CONSENT_FILE = '/home/chronos/Consent To Send Stats' |
| 15 _CORE_PATTERN = '/proc/sys/kernel/core_pattern' | 69 _CORE_PATTERN = '/proc/sys/kernel/core_pattern' |
| 16 _CRASH_REPORTER_PATH = '/sbin/crash_reporter' | 70 _CRASH_REPORTER_PATH = '/sbin/crash_reporter' |
| 17 _CRASH_SENDER_PATH = '/sbin/crash_sender' | 71 _CRASH_SENDER_PATH = '/sbin/crash_sender' |
| 18 _CRASH_SENDER_RATE_DIR = '/var/lib/crash_sender' | 72 _CRASH_SENDER_RATE_DIR = '/var/lib/crash_sender' |
| 19 _CRASH_SENDER_RUN_PATH = '/var/run/crash_sender.pid' | 73 _CRASH_SENDER_RUN_PATH = '/var/run/crash_sender.pid' |
| 20 _MOCK_CRASH_SENDING = '/tmp/mock-crash-sending' | 74 _MOCK_CRASH_SENDING = '/tmp/mock-crash-sending' |
| 21 _PAUSE_FILE = '/var/lib/crash_sender_paused' | 75 _PAUSE_FILE = '/var/lib/crash_sender_paused' |
| 22 _SYSTEM_CRASH_DIR = '/var/spool/crash' | 76 _SYSTEM_CRASH_DIR = '/var/spool/crash' |
| 23 _USER_CRASH_DIR = '/home/chronos/user/crash' | 77 _USER_CRASH_DIR = '/home/chronos/user/crash' |
| 24 | 78 |
| 25 def _set_system_sending(self, is_enabled): | 79 def _set_system_sending(self, is_enabled): |
| 26 """Sets whether or not the system crash_sender is allowed to run. | 80 """Sets whether or not the system crash_sender is allowed to run. |
| 27 | 81 |
| 82 This is done by creating or removing _PAUSE_FILE. | |
| 83 | |
| 28 crash_sender may still be allowed to run if _set_child_sending is | 84 crash_sender may still be allowed to run if _set_child_sending is |
| 29 called with true and it is run as a child process.""" | 85 called with True and it is run as a child process. |
| 86 | |
| 87 Args: | |
| 88 is_enabled: True to enable crash_sender, False to disable it. | |
| 89 """ | |
| 30 if is_enabled: | 90 if is_enabled: |
| 31 if os.path.exists(self._PAUSE_FILE): | 91 if os.path.exists(self._PAUSE_FILE): |
| 32 os.remove(self._PAUSE_FILE) | 92 os.remove(self._PAUSE_FILE) |
| 33 else: | 93 else: |
| 34 utils.system('touch ' + self._PAUSE_FILE) | 94 utils.system('touch ' + self._PAUSE_FILE) |
| 35 | 95 |
| 36 | 96 |
| 37 def _set_child_sending(self, is_enabled): | 97 def _set_child_sending(self, is_enabled): |
| 38 """Overrides crash sending enabling for child processes.""" | 98 """Overrides crash sending enabling for child processes. |
| 99 | |
| 100 When the system crash sender is disabled this test can manually run | |
| 101 the crash sender as a child process. Normally this would do nothing, | |
| 102 but this function sets up crash_sender to ignore its disabled status | |
| 103 and do its job. | |
| 104 | |
| 105 Args: | |
| 106 is_enabled: True to enable crash sending for child processes. | |
| 107 """ | |
| 39 if is_enabled: | 108 if is_enabled: |
| 40 os.environ['OVERRIDE_PAUSE_SENDING'] = "1" | 109 os.environ['OVERRIDE_PAUSE_SENDING'] = "1" |
| 41 else: | 110 else: |
| 42 del os.environ['OVERRIDE_PAUSE_SENDING'] | 111 del os.environ['OVERRIDE_PAUSE_SENDING'] |
| 43 | 112 |
| 44 | 113 |
| 45 def _reset_rate_limiting(self): | 114 def _reset_rate_limiting(self): |
| 115 """Reset the count of crash reports sent today. | |
| 116 | |
| 117 This clears the contents of the rate limiting directory which has | |
| 118 the effect of reseting our count of crash reports sent. | |
| 119 """ | |
| 46 utils.system('rm -rf ' + self._CRASH_SENDER_RATE_DIR) | 120 utils.system('rm -rf ' + self._CRASH_SENDER_RATE_DIR) |
| 47 | 121 |
| 48 | 122 |
| 49 def _clear_spooled_crashes(self): | 123 def _clear_spooled_crashes(self): |
| 124 """Clears system and user crash directories. | |
| 125 | |
| 126 This will remove all crash reports which are waiting to be sent. | |
| 127 """ | |
| 50 utils.system('rm -rf ' + self._SYSTEM_CRASH_DIR) | 128 utils.system('rm -rf ' + self._SYSTEM_CRASH_DIR) |
| 51 utils.system('rm -rf ' + self._USER_CRASH_DIR) | 129 utils.system('rm -rf ' + self._USER_CRASH_DIR) |
| 52 | 130 |
| 53 | 131 |
| 54 def _kill_running_sender(self): | 132 def _kill_running_sender(self): |
| 133 """Kill the the crash_sender process if running. | |
| 134 | |
| 135 We use the PID file to find the process ID, then kill it with signal 9. | |
| 136 """ | |
| 55 if not os.path.exists(self._CRASH_SENDER_RUN_PATH): | 137 if not os.path.exists(self._CRASH_SENDER_RUN_PATH): |
| 56 return | 138 return |
| 57 running_pid = int(utils.read_file(self._CRASH_SENDER_RUN_PATH)) | 139 running_pid = int(utils.read_file(self._CRASH_SENDER_RUN_PATH)) |
| 58 logging.warning('Detected running crash sender (%d), killing' % | 140 logging.warning('Detected running crash sender (%d), killing' % |
| 59 running_pid) | 141 running_pid) |
| 60 utils.system('kill -9 %d' % running_pid) | 142 utils.system('kill -9 %d' % running_pid) |
| 61 os.remove(self._CRASH_SENDER_RUN_PATH) | 143 os.remove(self._CRASH_SENDER_RUN_PATH) |
| 62 | 144 |
| 63 | 145 |
| 64 def _set_sending_mock(self, mock_enabled, send_success=True): | 146 def _set_sending_mock(self, mock_enabled, send_success=True): |
| 147 """Enables / disables mocking of the sending process. | |
| 148 | |
| 149 This uses the _MOCK_CRASH_SENDING file to achieve its aims. See notes | |
| 150 at the top. | |
| 151 | |
| 152 Args: | |
| 153 mock_enabled: If True, mocking is enabled, else it is disabled. | |
| 154 send_success: If mock_enabled this is True for the mocking to | |
| 155 indicate success, False to indicate failure. | |
| 156 """ | |
| 65 if mock_enabled: | 157 if mock_enabled: |
| 66 if send_success: | 158 if send_success: |
| 67 data = '' | 159 data = '' |
| 68 else: | 160 else: |
| 69 data = '1' | 161 data = '1' |
| 70 logging.info('Setting sending mock') | 162 logging.info('Setting sending mock') |
| 71 utils.open_write_close(self._MOCK_CRASH_SENDING, data) | 163 utils.open_write_close(self._MOCK_CRASH_SENDING, data) |
| 72 else: | 164 else: |
| 73 utils.system('rm -f ' + self._MOCK_CRASH_SENDING) | 165 utils.system('rm -f ' + self._MOCK_CRASH_SENDING) |
| 74 | 166 |
| 75 | 167 |
| 76 def _set_consent(self, has_consent): | 168 def _set_consent(self, has_consent): |
| 169 """Sets whether or not we have consent to send crash reports. | |
| 170 | |
| 171 This creates or deletes the _CONSENT_FILE to control whether | |
| 172 crash_sender will consider that it has consent to send crash reports. | |
| 173 | |
| 174 Args: | |
| 175 has_consent: True to indicate consent, False otherwise | |
| 176 """ | |
| 77 if has_consent: | 177 if has_consent: |
| 78 utils.open_write_close(self._CONSENT_FILE, 'test-consent') | 178 utils.open_write_close(self._CONSENT_FILE, 'test-consent') |
| 79 logging.info('Created ' + self._CONSENT_FILE) | 179 logging.info('Created ' + self._CONSENT_FILE) |
| 80 else: | 180 else: |
| 81 utils.system('rm -f "%s"' % (self._CONSENT_FILE)) | 181 utils.system('rm -f "%s"' % (self._CONSENT_FILE)) |
| 82 | 182 |
| 83 | 183 |
| 84 def _get_pushed_consent_file_path(self): | 184 def _get_pushed_consent_file_path(self): |
| 185 """Returns filename of the pushed consent file.""" | |
| 85 return os.path.join(self.bindir, 'pushed_consent') | 186 return os.path.join(self.bindir, 'pushed_consent') |
| 86 | 187 |
| 87 | 188 |
| 88 def _push_consent(self): | 189 def _push_consent(self): |
| 190 """Push the consent file, thus disabling consent. | |
| 191 | |
| 192 The consent file can be created in the new test if required. Call | |
| 193 _pop_consent() to restore the original state. | |
| 194 """ | |
| 89 if os.path.exists(self._CONSENT_FILE): | 195 if os.path.exists(self._CONSENT_FILE): |
| 90 shutil.move(self._CONSENT_FILE, | 196 shutil.move(self._CONSENT_FILE, |
| 91 self._get_pushed_consent_file_path()) | 197 self._get_pushed_consent_file_path()) |
| 92 | 198 |
| 93 | 199 |
| 94 def _pop_consent(self): | 200 def _pop_consent(self): |
| 201 """Pop the consent file, enabling/disabling consent as it was before | |
| 202 we pushed the consent.""" | |
| 95 self._set_consent(False) | 203 self._set_consent(False) |
| 96 if os.path.exists(self._get_pushed_consent_file_path()): | 204 if os.path.exists(self._get_pushed_consent_file_path()): |
| 97 shutil.move(self._get_pushed_consent_file_path(), | 205 shutil.move(self._get_pushed_consent_file_path(), |
| 98 self._CONSENT_FILE) | 206 self._CONSENT_FILE) |
| 99 | 207 |
| 100 | 208 |
| 101 def _get_crash_dir(self, username): | 209 def _get_crash_dir(self, username): |
| 210 """Returns full path to the crash directory for a given username | |
| 211 | |
| 212 Args: | |
| 213 username: username to use: | |
| 214 'chronos': Returns user crash directory. | |
| 215 'root': Returns system crash directory. | |
| 216 """ | |
| 102 if username == 'chronos': | 217 if username == 'chronos': |
| 103 return self._USER_CRASH_DIR | 218 return self._USER_CRASH_DIR |
| 104 else: | 219 else: |
| 105 return self._SYSTEM_CRASH_DIR | 220 return self._SYSTEM_CRASH_DIR |
| 106 | 221 |
| 107 | 222 |
| 108 def _initialize_crash_reporter(self): | 223 def _initialize_crash_reporter(self): |
| 224 """Start up the crash reporter.""" | |
| 109 utils.system('%s --init --nounclean_check' % self._CRASH_REPORTER_PATH) | 225 utils.system('%s --init --nounclean_check' % self._CRASH_REPORTER_PATH) |
| 110 # Completely disable crash_reporter from generating crash dumps | 226 # Completely disable crash_reporter from generating crash dumps |
| 111 # while any tests are running, otherwise a crashy system can make | 227 # while any tests are running, otherwise a crashy system can make |
| 112 # these tests flaky. | 228 # these tests flaky. |
| 113 self.enable_crash_filtering('none') | 229 self.enable_crash_filtering('none') |
| 114 | 230 |
| 115 | 231 |
| 116 def write_crash_dir_entry(self, name, contents): | 232 def write_crash_dir_entry(self, name, contents): |
| 233 """Writes an empty file to the system crash directory. | |
| 234 | |
| 235 This writes a file to _SYSTEM_CRASH_DIR with the given name. This is | |
| 236 used to insert new crash dump files for testing purposes. | |
| 237 | |
| 238 Args: | |
| 239 name: Name of file to write. | |
| 240 contents: String to write to the file. | |
| 241 """ | |
| 117 entry = os.path.join(self._SYSTEM_CRASH_DIR, name) | 242 entry = os.path.join(self._SYSTEM_CRASH_DIR, name) |
| 118 if not os.path.exists(self._SYSTEM_CRASH_DIR): | 243 if not os.path.exists(self._SYSTEM_CRASH_DIR): |
| 119 os.makedirs(self._SYSTEM_CRASH_DIR) | 244 os.makedirs(self._SYSTEM_CRASH_DIR) |
| 120 utils.open_write_close(entry, contents) | 245 utils.open_write_close(entry, contents) |
| 121 return entry | 246 return entry |
| 122 | 247 |
| 123 | 248 |
| 124 def write_fake_meta(self, name, exec_name, payload, log=None, | 249 def write_fake_meta(self, name, exec_name, payload, log=None, |
| 125 complete=True): | 250 complete=True): |
| 251 """Writes a fake meta entry to the system crash directory. | |
| 252 | |
| 253 Args: | |
| 254 name: Name of file to write. | |
| 255 exec_name: Value for exec_name item. | |
| 256 payload: Value for payload item. | |
| 257 log: Value for log item. | |
| 258 complete: True to close off the record, otherwise leave it | |
| 259 incomplete. | |
| 260 """ | |
| 126 last_line = '' | 261 last_line = '' |
| 127 if complete: | 262 if complete: |
| 128 last_line = 'done=1\n' | 263 last_line = 'done=1\n' |
| 129 contents = ('exec_name=%s\n' | 264 contents = ('exec_name=%s\n' |
| 130 'ver=my_ver\n' | 265 'ver=my_ver\n' |
| 131 'payload=%s\n' | 266 'payload=%s\n' |
| 132 '%s' % (exec_name, payload, | 267 '%s' % (exec_name, payload, |
| 133 last_line)) | 268 last_line)) |
| 134 if log: | 269 if log: |
| 135 contents = ('log=%s\n' % log) + contents | 270 contents = ('log=%s\n' % log) + contents |
| 136 return self.write_crash_dir_entry(name, contents) | 271 return self.write_crash_dir_entry(name, contents) |
| 137 | 272 |
| 138 | 273 |
| 139 def _prepare_sender_one_crash(self, | 274 def _prepare_sender_one_crash(self, |
| 140 send_success, | 275 send_success, |
| 141 reports_enabled, | 276 reports_enabled, |
| 142 username, | 277 username, |
| 143 report): | 278 report): |
| 279 """Create metadata for a fake crash report. | |
| 280 | |
| 281 This enabled mocking of the crash sender, then creates a fake | |
| 282 crash report for testing purposes. | |
| 283 | |
| 284 Args: | |
| 285 send_success: True to make the crash_sender success, False to make | |
| 286 it fail. | |
| 287 reports_enabled: True to enable consent to that reports will be | |
| 288 sent. | |
| 289 **username: not used | |
|
kmixter1
2011/02/25 00:15:15
Feel free to remove this.
| |
| 290 report: Report to use for crash, if None we create one. | |
| 291 """ | |
| 144 self._set_sending_mock(mock_enabled=True, send_success=send_success) | 292 self._set_sending_mock(mock_enabled=True, send_success=send_success) |
| 145 self._set_consent(reports_enabled) | 293 self._set_consent(reports_enabled) |
| 146 if report is None: | 294 if report is None: |
| 147 payload = self.write_crash_dir_entry('fake.dmp', '') | 295 payload = self.write_crash_dir_entry('fake.dmp', '') |
| 148 report = self.write_fake_meta('fake.meta', 'fake', payload) | 296 report = self.write_fake_meta('fake.meta', 'fake', payload) |
| 149 return report | 297 return report |
| 150 | 298 |
| 151 | 299 |
| 152 def _parse_sender_output(self, output): | 300 def _parse_sender_output(self, output): |
| 153 """Parse the log output from the crash_sender script. | 301 """Parse the log output from the crash_sender script. |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 284 # Show the result for debugging but remove 'output' key | 432 # Show the result for debugging but remove 'output' key |
| 285 # since it's large and earlier in debug output. | 433 # since it's large and earlier in debug output. |
| 286 debug_result = dict(result) | 434 debug_result = dict(result) |
| 287 del debug_result['output'] | 435 del debug_result['output'] |
| 288 logging.debug('Result of send (besides output): %s' % debug_result) | 436 logging.debug('Result of send (besides output): %s' % debug_result) |
| 289 | 437 |
| 290 return result | 438 return result |
| 291 | 439 |
| 292 | 440 |
| 293 def _replace_crash_reporter_filter_in(self, new_parameter): | 441 def _replace_crash_reporter_filter_in(self, new_parameter): |
| 442 """Replaces the --filter_in= parameter of the crash reporter. | |
| 443 | |
| 444 The kernel is set up to call the crash reporter with the core dump | |
| 445 as stdin when a process dies. This function adds a filter to the | |
| 446 command line used to call the crash reporter. This is used to ignore | |
| 447 crashes in which we have no interest. | |
| 448 | |
| 449 This removes any --filter_in= parameter and optionally replaces it | |
| 450 with a new one. | |
| 451 | |
| 452 Args: | |
| 453 new_parameter: This is parameter to add to the command line | |
| 454 instead of the --filter_in=... that was there. | |
| 455 """ | |
| 294 core_pattern = utils.read_file(self._CORE_PATTERN)[:-1] | 456 core_pattern = utils.read_file(self._CORE_PATTERN)[:-1] |
| 295 core_pattern = re.sub('--filter_in=\S*\s*', '', | 457 core_pattern = re.sub('--filter_in=\S*\s*', '', |
| 296 core_pattern).rstrip() | 458 core_pattern).rstrip() |
| 297 if new_parameter: | 459 if new_parameter: |
| 298 core_pattern += ' ' + new_parameter | 460 core_pattern += ' ' + new_parameter |
| 299 utils.system('echo "%s" > %s' % (core_pattern, self._CORE_PATTERN)) | 461 utils.system('echo "%s" > %s' % (core_pattern, self._CORE_PATTERN)) |
| 300 | 462 |
| 301 | 463 |
| 302 def enable_crash_filtering(self, name): | 464 def enable_crash_filtering(self, name): |
| 465 """Add a --filter_in argument to the kernel core dump cmdline. | |
| 466 | |
| 467 Args: | |
| 468 name: Filter text to use. This is passed as a --filter_in | |
| 469 argument to the crash reporter. | |
| 470 """ | |
| 303 self._replace_crash_reporter_filter_in('--filter_in=' + name) | 471 self._replace_crash_reporter_filter_in('--filter_in=' + name) |
| 304 | 472 |
| 305 | 473 |
| 306 def disable_crash_filtering(self): | 474 def disable_crash_filtering(self): |
| 475 """Remove the --filter_in argument from the kernel core dump cmdline. | |
| 476 | |
| 477 Next time the crash reporter is invoked (due to a crash) it will not | |
| 478 receive a --filter_in paramter.""" | |
| 307 self._replace_crash_reporter_filter_in('') | 479 self._replace_crash_reporter_filter_in('') |
| 308 | 480 |
| 309 | 481 |
| 310 def initialize(self): | 482 def initialize(self): |
| 483 """Initalize the test.""" | |
| 311 test.test.initialize(self) | 484 test.test.initialize(self) |
| 312 self._log_reader = cros_logging.LogReader() | 485 self._log_reader = cros_logging.LogReader() |
| 313 self._leave_crash_sending = True | 486 self._leave_crash_sending = True |
| 314 self._automatic_consent_saving = True | 487 self._automatic_consent_saving = True |
| 315 self.enable_crash_filtering('none') | 488 self.enable_crash_filtering('none') |
| 316 | 489 |
| 317 | 490 |
| 318 def cleanup(self): | 491 def cleanup(self): |
| 492 """Cleanup after the test. | |
| 493 | |
| 494 We reset things back to the way we think they should be. This is | |
| 495 intended to allow the system to continue normal operation. | |
| 496 | |
| 497 - Reset rate limiting. | |
|
kmixter1
2011/02/25 00:15:15
I'd prefer not to list things at this level since
| |
| 498 - Clear any spooled crashes. | |
| 499 - Turn off mocking of crash sending. | |
| 500 - Maybe pop the consent. | |
| 501 - disable filtering of crash info. | |
| 502 | |
| 503 Some variables change the behavior: | |
| 504 _automatic_consent_saving: if True, we pop the consent file. | |
| 505 _leave_crash_sending: True to enable crash sending, False to | |
| 506 disable it | |
| 507 """ | |
| 319 self._reset_rate_limiting() | 508 self._reset_rate_limiting() |
| 320 self._clear_spooled_crashes() | 509 self._clear_spooled_crashes() |
| 321 self._set_system_sending(self._leave_crash_sending) | 510 self._set_system_sending(self._leave_crash_sending) |
| 322 self._set_sending_mock(mock_enabled=False) | 511 self._set_sending_mock(mock_enabled=False) |
| 323 if self._automatic_consent_saving: | 512 if self._automatic_consent_saving: |
| 324 self._pop_consent() | 513 self._pop_consent() |
| 325 self.disable_crash_filtering() | 514 self.disable_crash_filtering() |
| 326 test.test.cleanup(self) | 515 test.test.cleanup(self) |
| 327 | 516 |
| 328 | 517 |
| 329 def run_crash_tests(self, | 518 def run_crash_tests(self, |
| 330 test_names, | 519 test_names, |
| 331 initialize_crash_reporter=False, | 520 initialize_crash_reporter=False, |
| 332 clear_spool_first=True, | 521 clear_spool_first=True, |
| 333 must_run_all=True): | 522 must_run_all=True): |
| 334 """Run crash tests defined in this class. | 523 """Run crash tests defined in this class. |
| 335 | 524 |
| 336 Args: | 525 Args: |
| 337 test_names: array of test names | 526 test_names: Array of test names. |
| 338 initialize_crash_reporter: should set up crash reporter for every run | 527 initialize_crash_reporter: Should set up crash reporter for every |
| 339 must_run_all: should make sure every test in this class is mentioned | 528 run. |
| 340 in test_names | 529 clear_spool_first: Clear all spooled user/system crashes before |
| 530 starting the test. | |
| 531 must_run_all: Should make sure every test in this class is | |
| 532 mentioned in test_names. | |
| 341 """ | 533 """ |
| 342 if self._automatic_consent_saving: | 534 if self._automatic_consent_saving: |
| 343 self._push_consent() | 535 self._push_consent() |
| 344 | 536 |
| 345 if must_run_all: | 537 if must_run_all: |
| 346 # Sanity check test_names is complete | 538 # Sanity check test_names is complete |
| 347 for attr in dir(self): | 539 for attr in dir(self): |
| 348 if attr.find('_test_') == 0: | 540 if attr.find('_test_') == 0: |
| 349 test_name = attr[6:] | 541 test_name = attr[6:] |
| 350 if not test_name in test_names: | 542 if not test_name in test_names: |
| 351 raise error.TestError('Test %s is missing' % test_name) | 543 raise error.TestError('Test %s is missing' % test_name) |
| 352 | 544 |
| 353 for test_name in test_names: | 545 for test_name in test_names: |
| 354 logging.info(('=' * 20) + ('Running %s' % test_name) + ('=' * 20)) | 546 logging.info(('=' * 20) + ('Running %s' % test_name) + ('=' * 20)) |
| 355 if initialize_crash_reporter: | 547 if initialize_crash_reporter: |
| 356 self._initialize_crash_reporter() | 548 self._initialize_crash_reporter() |
| 357 # Disable crash_sender from running, kill off any running ones, but | 549 # Disable crash_sender from running, kill off any running ones, but |
| 358 # set environment so crash_sender may run as a child process. | 550 # set environment so crash_sender may run as a child process. |
| 359 self._set_system_sending(False) | 551 self._set_system_sending(False) |
| 360 self._set_child_sending(True) | 552 self._set_child_sending(True) |
| 361 self._kill_running_sender() | 553 self._kill_running_sender() |
| 362 self._reset_rate_limiting() | 554 self._reset_rate_limiting() |
| 363 if clear_spool_first: | 555 if clear_spool_first: |
| 364 self._clear_spooled_crashes() | 556 self._clear_spooled_crashes() |
| 557 | |
| 558 # Call the test function | |
| 365 getattr(self, '_test_' + test_name)() | 559 getattr(self, '_test_' + test_name)() |
| OLD | NEW |