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