Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(693)

Side by Side Diff: client/site_tests/logging_UserCrash/logging_UserCrash.py

Issue 3450004: Deprecated libcrash.a so stop testing it (Closed) Base URL: http://git.chromium.org/git/autotest.git
Patch Set: Remove all traces of with-breakpad tests Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | client/site_tests/logging_UserCrash/src/Makefile » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 grp, logging, os, pwd, re, stat, subprocess 5 import grp, logging, os, pwd, re, stat, subprocess
6 from signal import SIGSEGV 6 from signal import SIGSEGV
7 from autotest_lib.client.bin import site_crash_test, site_utils, test 7 from autotest_lib.client.bin import site_crash_test, site_utils, test
8 from autotest_lib.client.common_lib import error, utils 8 from autotest_lib.client.common_lib import error, utils
9 9
10 _CORE_PATTERN = '/proc/sys/kernel/core_pattern' 10 _CORE_PATTERN = '/proc/sys/kernel/core_pattern'
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 if output != 'core': 45 if output != 'core':
46 raise error.TestFail('core pattern should have been core, not %s' % 46 raise error.TestFail('core pattern should have been core, not %s' %
47 output) 47 output)
48 48
49 49
50 def _prepare_crasher(self): 50 def _prepare_crasher(self):
51 """Extract the crasher and set its permissions. 51 """Extract the crasher and set its permissions.
52 52
53 crasher is only gzipped to subvert Portage stripping. 53 crasher is only gzipped to subvert Portage stripping.
54 """ 54 """
55 self._crasher_path = { 55 self._crasher_path = os.path.join(self.srcdir, 'crasher_nobreakpad')
56 True: os.path.join(self.srcdir, 'crasher_breakpad'),
57 False: os.path.join(self.srcdir, 'crasher_nobreakpad')
58 }
59 utils.system('cd %s; tar xzf crasher.tgz' % 56 utils.system('cd %s; tar xzf crasher.tgz' %
60 self.srcdir) 57 self.srcdir)
61 58
62 59
63 def _populate_symbols(self): 60 def _populate_symbols(self):
64 """Set up Breakpad's symbol structure. 61 """Set up Breakpad's symbol structure.
65 62
66 Breakpad's minidump processor expects symbols to be in a directory 63 Breakpad's minidump processor expects symbols to be in a directory
67 hierarchy: 64 hierarchy:
68 <symbol-root>/<module_name>/<file_id>/<module_name>.sym 65 <symbol-root>/<module_name>/<file_id>/<module_name>.sym
69 """ 66 """
70 # Dump the symbols from the crasher 67 # Dump the symbols from the crasher
71 self._symbol_dir = os.path.join(self.srcdir, 'symbols') 68 self._symbol_dir = os.path.join(self.srcdir, 'symbols')
72 utils.system('rm -rf %s' % self._symbol_dir) 69 utils.system('rm -rf %s' % self._symbol_dir)
73 os.mkdir(self._symbol_dir) 70 os.mkdir(self._symbol_dir)
74 71
75 for with_breakpad in [True, False]: 72 basename = os.path.basename(self._crasher_path)
76 basename = os.path.basename(self._crasher_path[with_breakpad]) 73 utils.system('/usr/bin/dump_syms %s > %s.sym' %
77 utils.system('/usr/bin/dump_syms %s > %s.sym' % 74 (self._crasher_path,
78 (self._crasher_path[with_breakpad], 75 basename))
79 basename)) 76 sym_name = '%s.sym' % basename
80 sym_name = '%s.sym' % basename 77 symbols = utils.read_file(sym_name)
81 symbols = utils.read_file(sym_name) 78 # First line should be like:
82 # First line should be like: 79 # MODULE Linux x86 7BC3323FBDBA2002601FA5BA3186D6540 crasher_XXX
83 # MODULE Linux x86 7BC3323FBDBA2002601FA5BA3186D6540 crasher_XXX 80 # or
84 # or 81 # MODULE Linux arm C2FE4895B203D87DD4D9227D5209F7890 crasher_XXX
85 # MODULE Linux arm C2FE4895B203D87DD4D9227D5209F7890 crasher_XXX 82 first_line = symbols.split('\n')[0]
86 first_line = symbols.split('\n')[0] 83 tokens = first_line.split()
87 tokens = first_line.split() 84 if tokens[0] != 'MODULE' or tokens[1] != 'Linux':
88 if tokens[0] != 'MODULE' or tokens[1] != 'Linux': 85 raise error.TestError('Unexpected symbols format: %s',
89 raise error.TestError('Unexpected symbols format: %s', 86 first_line)
90 first_line) 87 file_id = tokens[3]
91 file_id = tokens[3] 88 target_dir = os.path.join(self._symbol_dir, basename, file_id)
92 target_dir = os.path.join(self._symbol_dir, basename, file_id) 89 os.makedirs(target_dir)
93 os.makedirs(target_dir) 90 os.rename(sym_name, os.path.join(target_dir, sym_name))
94 os.rename(sym_name, os.path.join(target_dir, sym_name))
95 91
96 92
97 def _verify_stack(self, stack, basename, from_crash_reporter): 93 def _verify_stack(self, stack, basename, from_crash_reporter):
98 logging.debug('Crash stackwalk was: %s' % stack) 94 logging.debug('Crash stackwalk was: %s' % stack)
99 95
100 # Should identify cause as SIGSEGV at address 0x16 96 # Should identify cause as SIGSEGV at address 0x16
101 match = re.search(r'Crash reason:\s+(.*)', stack) 97 match = re.search(r'Crash reason:\s+(.*)', stack)
102 expected_address = '0x16' 98 expected_address = '0x16'
103 if from_crash_reporter: 99 if from_crash_reporter:
104 # We cannot yet determine the crash address when coming 100 # We cannot yet determine the crash address when coming
(...skipping 13 matching lines...) Expand all
118 # Should identify recursion line which is on the stack 114 # Should identify recursion line which is on the stack
119 # for 15 levels 115 # for 15 levels
120 if not ('15 %s!recbomb(int) [bomb.cc : 12 ' % basename) in stack: 116 if not ('15 %s!recbomb(int) [bomb.cc : 12 ' % basename) in stack:
121 raise error.TestFail('Did not show recursion line on stack') 117 raise error.TestFail('Did not show recursion line on stack')
122 118
123 # Should identify main line 119 # Should identify main line
124 if not ('16 %s!main [crasher.cc : 21 ' % basename) in stack: 120 if not ('16 %s!main [crasher.cc : 21 ' % basename) in stack:
125 raise error.TestFail('Did not show main on stack') 121 raise error.TestFail('Did not show main on stack')
126 122
127 123
128 def _run_crasher_process(self, username, with_breakpad, cause_crash=True): 124 def _run_crasher_process(self, username, cause_crash=True):
129 """Runs the crasher process. 125 """Runs the crasher process.
130 126
131 Args: 127 Args:
132 username: runs as given user 128 username: runs as given user
133 with_breakpad: run crasher that has breakpad (-lcrash) linked in
134 extra_args: additional parameters to pass to crasher process 129 extra_args: additional parameters to pass to crasher process
135 130
136 Returns: 131 Returns:
137 A dictionary with keys: 132 A dictionary with keys:
138 returncode: return code of the crasher 133 returncode: return code of the crasher
139 crashed: did the crasher return segv error code 134 crashed: did the crasher return segv error code
140 crash_reporter_caught: did crash_reporter catch a segv 135 crash_reporter_caught: did crash_reporter catch a segv
141 output: stderr/stdout output of the crasher process 136 output: stderr/stdout output of the crasher process
142 """ 137 """
143 self._prepare_crasher() 138 self._prepare_crasher()
144 self._populate_symbols() 139 self._populate_symbols()
145 140
146 if username != 'root': 141 if username != 'root':
147 crasher_command = ['su', username, '-c'] 142 crasher_command = ['su', username, '-c']
148 expected_result = 128 + SIGSEGV 143 expected_result = 128 + SIGSEGV
149 else: 144 else:
150 crasher_command = [] 145 crasher_command = []
151 expected_result = -SIGSEGV 146 expected_result = -SIGSEGV
152 147
153 crasher_command.append(self._crasher_path[with_breakpad]) 148 crasher_command.append(self._crasher_path)
154 basename = os.path.basename(self._crasher_path[with_breakpad]) 149 basename = os.path.basename(self._crasher_path)
155 if not cause_crash: 150 if not cause_crash:
156 crasher_command.append('--nocrash') 151 crasher_command.append('--nocrash')
157 crasher = subprocess.Popen(crasher_command, 152 crasher = subprocess.Popen(crasher_command,
158 stdout=subprocess.PIPE, 153 stdout=subprocess.PIPE,
159 stderr=subprocess.PIPE) 154 stderr=subprocess.PIPE)
160 output = crasher.communicate()[1] 155 output = crasher.communicate()[1]
161 logging.debug('Output from %s: %s' % 156 logging.debug('Output from %s: %s' %
162 (self._crasher_path[with_breakpad], output)) 157 (self._crasher_path, output))
163 158
164 # Grab the pid from the process output. We can't just use 159 # Grab the pid from the process output. We can't just use
165 # crasher.pid unfortunately because that may be the PID of su. 160 # crasher.pid unfortunately because that may be the PID of su.
166 match = re.search(r'pid=(\d+)', output) 161 match = re.search(r'pid=(\d+)', output)
167 if not match: 162 if not match:
168 raise error.TestFail('Could not find pid output from crasher: %s' % 163 raise error.TestFail('Could not find pid output from crasher: %s' %
169 output) 164 output)
170 pid = int(match.group(1)) 165 pid = int(match.group(1))
171 166
172 expected_message = ('Received crash notification for ' 167 expected_message = ('Received crash notification for '
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 raise error.TestFail('Minidump not sent properly') 233 raise error.TestFail('Minidump not sent properly')
239 if will_syslog_give_name: 234 if will_syslog_give_name:
240 if result['exec_name'] != crasher_basename: 235 if result['exec_name'] != crasher_basename:
241 raise error.TestFail('Executable name incorrect') 236 raise error.TestFail('Executable name incorrect')
242 if result['report_kind'] != 'minidump': 237 if result['report_kind'] != 'minidump':
243 raise error.TestFail('Expected a minidump report') 238 raise error.TestFail('Expected a minidump report')
244 if result['report_name'] != minidump_path: 239 if result['report_name'] != minidump_path:
245 raise error.TestFail('Sent the wrong minidump report') 240 raise error.TestFail('Sent the wrong minidump report')
246 241
247 242
248 def _check_crashing_process(self, username, with_breakpad): 243 def _check_crashing_process(self, username):
249 self._log_reader.set_start_by_current() 244 self._log_reader.set_start_by_current()
250 245
251 result = self._run_crasher_process(username, with_breakpad) 246 result = self._run_crasher_process(username)
252 247
253 if not result['crashed']: 248 if not result['crashed']:
254 raise error.TestFail('crasher did not do its job of crashing: %d' % 249 raise error.TestFail('crasher did not do its job of crashing: %d' %
255 result['returncode']) 250 result['returncode'])
256 251
257 if not result['crash_reporter_caught']: 252 if not result['crash_reporter_caught']:
258 logging.debug('Messages that should have included segv: %s' % 253 logging.debug('Messages that should have included segv: %s' %
259 self._log_reader.get_logs()) 254 self._log_reader.get_logs())
260 raise error.TestFail('Did not find segv message') 255 raise error.TestFail('Did not find segv message')
261 256
262 crash_dir = self._get_crash_dir(username) 257 crash_dir = self._get_crash_dir(username)
263 crash_contents = os.listdir(crash_dir) 258 crash_contents = os.listdir(crash_dir)
264 basename = os.path.basename(self._crasher_path[with_breakpad]) 259 basename = os.path.basename(self._crasher_path)
265 260
266 breakpad_minidump = None 261 breakpad_minidump = None
267 crash_reporter_minidump = None 262 crash_reporter_minidump = None
268 263
269 self._check_crash_directory_permissions(crash_dir) 264 self._check_crash_directory_permissions(crash_dir)
270 265
271 logging.debug('Contents in %s: %s' % (crash_dir, crash_contents)) 266 logging.debug('Contents in %s: %s' % (crash_dir, crash_contents))
272 267
273 for filename in crash_contents: 268 for filename in crash_contents:
274 if filename.endswith('.core'): 269 if filename.endswith('.core'):
275 # Ignore core files. We'll test them later. 270 # Ignore core files. We'll test them later.
276 pass 271 pass
277 elif filename.startswith(basename): 272 elif filename.startswith(basename):
278 # This appears to be a minidump created by the crash reporter. 273 # This appears to be a minidump created by the crash reporter.
279 if not crash_reporter_minidump is None: 274 if not crash_reporter_minidump is None:
280 raise error.TestFail('Crash reporter wrote multiple ' 275 raise error.TestFail('Crash reporter wrote multiple '
281 'minidumps') 276 'minidumps')
282 crash_reporter_minidump = os.path.join(crash_dir, filename) 277 crash_reporter_minidump = os.path.join(crash_dir, filename)
283 else: 278 else:
284 # This appears to be a breakpad created minidump. 279 # This appears to be a breakpad created minidump.
285 if not breakpad_minidump is None: 280 if not breakpad_minidump is None:
286 raise error.TestFail('Breakpad wrote multimpe minidumps') 281 raise error.TestFail('Breakpad wrote multimpe minidumps')
287 breakpad_minidump = os.path.join(crash_dir, filename) 282 breakpad_minidump = os.path.join(crash_dir, filename)
288 283
289 if with_breakpad and not breakpad_minidump: 284 if breakpad_minidump:
290 raise error.TestFail('%s did not generate breakpad minidump' %
291 basename)
292
293 if not with_breakpad and breakpad_minidump:
294 raise error.TestFail('%s did generate breakpad minidump' % basename) 285 raise error.TestFail('%s did generate breakpad minidump' % basename)
295 286
296 if not crash_reporter_minidump: 287 if not crash_reporter_minidump:
297 raise error.TestFail('crash reporter did not generate minidump') 288 raise error.TestFail('crash reporter did not generate minidump')
298 289
299 if not self._log_reader.can_find('Stored minidump to ' + 290 if not self._log_reader.can_find('Stored minidump to ' +
300 crash_reporter_minidump): 291 crash_reporter_minidump):
301 raise error.TestFail('crash reporter did not announce minidump') 292 raise error.TestFail('crash reporter did not announce minidump')
302 293
303 # By default test sending the crash_reporter minidump unless there 294 # By default test sending the crash_reporter minidump unless there
(...skipping 22 matching lines...) Expand all
326 317
327 self._check_generated_minidump_sending(send_minidump, 318 self._check_generated_minidump_sending(send_minidump,
328 username, 319 username,
329 basename, 320 basename,
330 will_syslog_give_name) 321 will_syslog_give_name)
331 322
332 def _test_no_crash(self): 323 def _test_no_crash(self):
333 """Test a program linked against libcrash_dumper can exit normally.""" 324 """Test a program linked against libcrash_dumper can exit normally."""
334 self._log_reader.set_start_by_current() 325 self._log_reader.set_start_by_current()
335 result = self._run_crasher_process(username='root', 326 result = self._run_crasher_process(username='root',
336 with_breakpad=True,
337 cause_crash=False) 327 cause_crash=False)
338 if (result['crashed'] or 328 if (result['crashed'] or
339 result['crash_reporter_caught'] or 329 result['crash_reporter_caught'] or
340 result['returncode'] != 0): 330 result['returncode'] != 0):
341 raise error.TestFail('Normal exit of program with dumper failed') 331 raise error.TestFail('Normal exit of program with dumper failed')
342 332
343 333
344 def _test_chronos_breakpad_crasher(self):
345 """Test a user space crash when running as chronos is handled."""
346 self._check_crashing_process('chronos', True)
347
348
349 def _test_chronos_nobreakpad_crasher(self): 334 def _test_chronos_nobreakpad_crasher(self):
350 """Test a user space crash when running as chronos is handled.""" 335 """Test a user space crash when running as chronos is handled."""
351 self._check_crashing_process('chronos', False) 336 self._check_crashing_process('chronos')
352
353
354 def _test_root_breakpad_crasher(self):
355 """Test a user space crash when running as root is handled."""
356 self._check_crashing_process('root', True)
357 337
358 338
359 def _test_root_nobreakpad_crasher(self): 339 def _test_root_nobreakpad_crasher(self):
360 """Test a user space crash when running as root is handled.""" 340 """Test a user space crash when running as root is handled."""
361 self._check_crashing_process('root', False) 341 self._check_crashing_process('root')
362 342
363 343
364 def _test_max_enqueued_crashes(self): 344 def _test_max_enqueued_crashes(self):
365 """Test that _MAX_CRASH_DIRECTORY_SIZE is enforced.""" 345 """Test that _MAX_CRASH_DIRECTORY_SIZE is enforced."""
366 self._log_reader.set_start_by_current() 346 self._log_reader.set_start_by_current()
367 username = 'root' 347 username = 'root'
368 348
369 crash_dir = self._get_crash_dir(username) 349 crash_dir = self._get_crash_dir(username)
370 full_message = ('Crash directory %s already full with %d pending ' 350 full_message = ('Crash directory %s already full with %d pending '
371 'reports' % (crash_dir, _MAX_CRASH_DIRECTORY_SIZE)) 351 'reports' % (crash_dir, _MAX_CRASH_DIRECTORY_SIZE))
372 352
373 # Fill up the queue. 353 # Fill up the queue.
374 for i in range(0, _MAX_CRASH_DIRECTORY_SIZE): 354 for i in range(0, _MAX_CRASH_DIRECTORY_SIZE):
375 result = self._run_crasher_process(username, with_breakpad=False) 355 result = self._run_crasher_process(username)
376 if not result['crashed']: 356 if not result['crashed']:
377 raise error.TestFail('failure while setting up queue: %d' % 357 raise error.TestFail('failure while setting up queue: %d' %
378 result['returncode']) 358 result['returncode'])
379 if self._log_reader.can_find(full_message): 359 if self._log_reader.can_find(full_message):
380 raise error.TestFail('unexpected full message: ' + full_message) 360 raise error.TestFail('unexpected full message: ' + full_message)
381 361
382 crash_dir_size = len(os.listdir(crash_dir)) 362 crash_dir_size = len(os.listdir(crash_dir))
383 # For debugging 363 # For debugging
384 utils.system('ls -l %s' % crash_dir) 364 utils.system('ls -l %s' % crash_dir)
385 logging.info('Crash directory had %d entries' % crash_dir_size) 365 logging.info('Crash directory had %d entries' % crash_dir_size)
386 366
387 # Crash a bunch more times, but make sure no new reports 367 # Crash a bunch more times, but make sure no new reports
388 # are enqueued. 368 # are enqueued.
389 for i in range(0, 10): 369 for i in range(0, 10):
390 self._log_reader.set_start_by_current() 370 self._log_reader.set_start_by_current()
391 result = self._run_crasher_process(username, with_breakpad=False) 371 result = self._run_crasher_process(username)
392 logging.info('New log messages: %s' % self._log_reader.get_logs()) 372 logging.info('New log messages: %s' % self._log_reader.get_logs())
393 if not result['crashed']: 373 if not result['crashed']:
394 raise error.TestFail('failure after setting up queue: %d' % 374 raise error.TestFail('failure after setting up queue: %d' %
395 result['returncode']) 375 result['returncode'])
396 if not self._log_reader.can_find(full_message): 376 if not self._log_reader.can_find(full_message):
397 raise error.TestFail('expected full message: ' + full_message) 377 raise error.TestFail('expected full message: ' + full_message)
398 378
399 if crash_dir_size != len(os.listdir(crash_dir)): 379 if crash_dir_size != len(os.listdir(crash_dir)):
400 utils.system('ls -l %s' % crash_dir) 380 utils.system('ls -l %s' % crash_dir)
401 raise error.TestFail('expected no new files (now %d were %d)', 381 raise error.TestFail('expected no new files (now %d were %d)',
402 len(os.listdir(crash_dir)), 382 len(os.listdir(crash_dir)),
403 crash_dir_size) 383 crash_dir_size)
404 384
405 385
406 def _check_core_file_persisting(self, expect_persist): 386 def _check_core_file_persisting(self, expect_persist):
407 self._log_reader.set_start_by_current() 387 self._log_reader.set_start_by_current()
408 388
409 result = self._run_crasher_process('root', with_breakpad=False) 389 result = self._run_crasher_process('root')
410 390
411 if not result['crashed']: 391 if not result['crashed']:
412 raise error.TestFail('crasher did not crash') 392 raise error.TestFail('crasher did not crash')
413 393
414 crash_contents = os.listdir(self._get_crash_dir('root')) 394 crash_contents = os.listdir(self._get_crash_dir('root'))
415 395
416 logging.debug('Contents of crash directory: %s', crash_contents) 396 logging.debug('Contents of crash directory: %s', crash_contents)
417 logging.debug('Log messages: %s' % self._log_reader.get_logs()) 397 logging.debug('Log messages: %s' % self._log_reader.get_logs())
418 398
419 if expect_persist: 399 if expect_persist:
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 os.system('umount /root') 443 os.system('umount /root')
464 444
465 445
466 # TODO(kmixter): Test crashing a process as ntp or some other 446 # TODO(kmixter): Test crashing a process as ntp or some other
467 # non-root, non-chronos user. 447 # non-root, non-chronos user.
468 448
469 def run_once(self): 449 def run_once(self):
470 self.run_crash_tests(['reporter_startup', 450 self.run_crash_tests(['reporter_startup',
471 'reporter_shutdown', 451 'reporter_shutdown',
472 'no_crash', 452 'no_crash',
473 'chronos_breakpad_crasher',
474 'chronos_nobreakpad_crasher', 453 'chronos_nobreakpad_crasher',
475 'root_breakpad_crasher',
476 'root_nobreakpad_crasher', 454 'root_nobreakpad_crasher',
477 'max_enqueued_crashes', 455 'max_enqueued_crashes',
478 'core_file_persists_in_debug', 456 'core_file_persists_in_debug',
479 'core_file_removed_in_production'], 457 'core_file_removed_in_production'],
480 initialize_crash_reporter = True) 458 initialize_crash_reporter = True)
OLDNEW
« no previous file with comments | « no previous file | client/site_tests/logging_UserCrash/src/Makefile » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698