Back to index

apport  2.3
Public Member Functions | Public Attributes
test_crashdb.T Class Reference

List of all members.

Public Member Functions

def setUp
def tearDown
def test_no_dummy_data
def test_retrace_markers
def test_dynamic_crashdb_conf
def test_accepts_default
def test_accepts_problem_types
def test_submit
def test_get_affected_packages
def test_update
def test_update_filter
def test_update_traces
def test_get_distro_release
def test_status
def test_mark_regression
def test_duplicate_db_fixed
def test_duplicate_db_remove
def test_check_duplicate
def test_check_duplicate_utf8
def test_check_duplicate_custom_signature
def test_check_duplicate_report_arg
def test_check_duplicate_multiple_masters
def test_known_address_sig
def test_duplicate_db_publish_long_sigs
def test_change_master_id
def test_db_corruption

Public Attributes

 workdir
 dupdb_dir
 crashes

Detailed Description

Definition at line 8 of file test_crashdb.py.


Member Function Documentation

def test_crashdb.T.setUp (   self)

Definition at line 9 of file test_crashdb.py.

00009 
00010     def setUp(self):
00011         self.workdir = tempfile.mkdtemp()
00012         self.dupdb_dir = os.path.join(self.workdir, 'dupdb')
00013         self.crashes = CrashDatabase(None, {'dummy_data': '1',
00014                                             'dupdb_url': 'file://' + self.dupdb_dir})
00015 
00016         self.assertEqual(self.crashes.get_comment_url(self.crashes.download(0), 0),
00017                          'http://foo.bugs.example.com/0')
00018 
00019         # test-suite internal consistency check: Python signatures are
00020         # indeed equal and exist
00021         assert self.crashes.download(3).crash_signature(), \
00022             'test-suite internal check: Python crash sigs exist'
00023         self.assertEqual(self.crashes.download(3).crash_signature(),
00024                          self.crashes.download(4).crash_signature())
00025 
00026         # we should have 5 crashes
00027         self.assertEqual(self.crashes.latest_id(), 4)

def test_crashdb.T.tearDown (   self)

Definition at line 28 of file test_crashdb.py.

00028 
00029     def tearDown(self):
00030         shutil.rmtree(self.workdir)

accepts(): default configuration

Definition at line 76 of file test_crashdb.py.

00076 
00077     def test_accepts_default(self):
00078         '''accepts(): default configuration'''
00079 
00080         # by default crash DBs accept any type
00081         self.assertTrue(self.crashes.accepts(apport.Report('Crash')))
00082         self.assertTrue(self.crashes.accepts(apport.Report('Bug')))
00083         self.assertTrue(self.crashes.accepts(apport.Report('weirdtype')))

accepts(): problem_types option in crashdb.conf

Definition at line 84 of file test_crashdb.py.

00084 
00085     def test_accepts_problem_types(self):
00086         '''accepts(): problem_types option in crashdb.conf'''
00087 
00088         # create a crash DB with type limits
00089         crashdb_conf = tempfile.NamedTemporaryFile()
00090         crashdb_conf.write(b'''default = 'testsuite'
00091 
00092 databases = {
00093     'testsuite': {
00094         'impl': 'memory',
00095         'problem_types': ['Bug', 'Kernel'],
00096     },
00097 }
00098 ''')
00099         crashdb_conf.flush()
00100 
00101         db = apport.crashdb.get_crashdb(None, None, crashdb_conf.name)
00102 
00103         self.assertTrue(db.accepts(apport.Report('Bug')))
00104         self.assertFalse(db.accepts(apport.Report('Crash')))
00105         self.assertFalse(db.accepts(apport.Report('weirdtype')))

Here is the call graph for this function:

duplicate_db_change_master_id()

Definition at line 634 of file test_crashdb.py.

00634 
00635     def test_change_master_id(self):
00636         '''duplicate_db_change_master_id()'''
00637 
00638         # db not yet initialized
00639         self.assertRaises(AssertionError, self.crashes.check_duplicate, 0)
00640 
00641         self.crashes.init_duplicate_db(':memory:')
00642 
00643         self.assertEqual(self.crashes.check_duplicate(0), None)
00644         self.assertEqual(self.crashes.check_duplicate(2), None)
00645 
00646         # check DB consistency
00647         self.assertEqual(self.crashes._duplicate_db_dump(),
00648                          {self.crashes.download(0).crash_signature(): (0, None),
00649                           self.crashes.download(2).crash_signature(): (2, None)})
00650 
00651         # invalid ID (raising KeyError is *hard*, so it's not done)
00652         self.crashes.duplicate_db_change_master_id(5, 99)
00653 
00654         # nevertheless, this should not change the DB
00655         self.assertEqual(self.crashes._duplicate_db_dump(),
00656                          {self.crashes.download(0).crash_signature(): (0, None),
00657                           self.crashes.download(2).crash_signature(): (2, None)})
00658 
00659         # valid ID
00660         self.crashes.duplicate_db_change_master_id(2, 99)
00661 
00662         # check DB consistency
00663         self.assertEqual(self.crashes._duplicate_db_dump(),
00664                          {self.crashes.download(0).crash_signature(): (0, None),
00665                           self.crashes.download(2).crash_signature(): (99, None)})

check_duplicate() and known()

Definition at line 254 of file test_crashdb.py.

00254 
00255     def test_check_duplicate(self):
00256         '''check_duplicate() and known()'''
00257 
00258         # db not yet initialized
00259         self.assertRaises(AssertionError, self.crashes.check_duplicate, 0,
00260                           self.crashes.download(0))
00261         self.assertRaises(AssertionError, self.crashes.check_duplicate, 0)
00262 
00263         self.crashes.init_duplicate_db(':memory:')
00264 
00265         self.assertEqual(self.crashes._duplicate_db_dump(), {})
00266 
00267         # ID#0 -> no dup
00268         self.assertEqual(self.crashes.known(self.crashes.download(0)), None)
00269         self.assertEqual(self.crashes.check_duplicate(0), None)
00270         # can't be known before publishing DB
00271         self.assertEqual(self.crashes.known(self.crashes.download(0)), None)
00272         self.crashes.duplicate_db_publish(self.dupdb_dir)
00273         self.assertEqual(self.crashes.known(self.crashes.download(0)),
00274                          'http://foo.bugs.example.com/0')
00275 
00276         # bug is not a duplicate of itself, when reprocessed
00277         self.assertEqual(self.crashes.check_duplicate(0), None)
00278 
00279         # ID#1 -> dup of #0
00280         self.crashes.duplicate_db_publish(self.dupdb_dir)
00281         self.assertEqual(self.crashes.known(self.crashes.download(1)),
00282                          'http://foo.bugs.example.com/0')
00283         self.assertEqual(self.crashes.check_duplicate(1), (0, None))
00284 
00285         # ID#2 is unrelated, no dup
00286         self.crashes.duplicate_db_publish(self.dupdb_dir)
00287         self.assertEqual(self.crashes.known(self.crashes.download(2)), None)
00288         self.assertEqual(self.crashes.check_duplicate(2), None)
00289         self.crashes.duplicate_db_publish(self.dupdb_dir)
00290         self.assertEqual(self.crashes.known(self.crashes.download(2)),
00291                          'http://bar.bugs.example.com/2')
00292 
00293         # ID#3: no dup, master of ID#4
00294         self.assertEqual(self.crashes.check_duplicate(3), None)
00295 
00296         # ID#4: dup of ID#3
00297         self.assertEqual(self.crashes.check_duplicate(4), (3, None))
00298         # not marked as regression
00299         self.assertFalse('comment' in self.crashes.reports[3])
00300 
00301         # check DB consistency; #1 and #4 are dupes and do not appear
00302         self.assertEqual(self.crashes._duplicate_db_dump(),
00303                          {self.crashes.download(0).crash_signature(): (0, None),
00304                           self.crashes.download(2).crash_signature(): (2, None),
00305                           self.crashes.download(3).crash_signature(): (3, None)})
00306 
00307         # now mark the python crash as fixed
00308         self.crashes.reports[3]['fixed_version'] = '4.1'
00309 
00310         # ID#4 is dup of ID#3, but happend in version 5 -> regression
00311         self.crashes.close_duplicate(self.crashes.download(4), 4, None)  # reset
00312         self.assertEqual(self.crashes.check_duplicate(4), None)
00313         self.assertEqual(self.crashes.duplicate_of(4), None)
00314         self.assertEqual(self.crashes.reports[4]['comment'], 'regression, already fixed in #3')
00315 
00316         # check DB consistency; ID#3 should now be updated to be fixed in 4.1,
00317         # and as 4 is a regression, appear as a new crash
00318         self.assertEqual(self.crashes._duplicate_db_dump(),
00319                          {self.crashes.download(0).crash_signature(): (0, None),
00320                           self.crashes.download(2).crash_signature(): (2, None),
00321                           self.crashes.download(3).crash_signature(): (3, '4.1'),
00322                           self.crashes.download(4).crash_signature(): (4, None)})
00323 
00324         # add two more  Python crash dups and verify that they are dup'ed
00325         # to the correct ID
00326         r = copy.copy(self.crashes.download(3))
00327         self.assertEqual(self.crashes.get_comment_url(r, self.crashes.upload(r)),
00328                          'http://pygoo.bugs.example.com/5')
00329         self.assertEqual(self.crashes.check_duplicate(5), (3, '4.1'))
00330         self.assertEqual(self.crashes.duplicate_of(5), 3)
00331         # not marked as regression, happened earlier than #3
00332         self.assertFalse('comment' in self.crashes.reports[5])
00333 
00334         r = copy.copy(self.crashes.download(3))
00335         r['Package'] = 'python-goo 5.1'
00336         self.assertEqual(self.crashes.get_comment_url(r, self.crashes.upload(r)),
00337                          'http://pygoo.bugs.example.com/6')
00338         self.assertEqual(self.crashes.check_duplicate(6), (4, None))
00339         self.assertEqual(self.crashes.duplicate_of(6), 4)
00340         # not marked as regression, as it's now a dupe of new master bug 4
00341         self.assertFalse('comment' in self.crashes.reports[6])
00342 
00343         # check DB consistency; #5 and #6 are dupes of #3 and #4, so no new
00344         # entries
00345         self.assertEqual(self.crashes._duplicate_db_dump(),
00346                          {self.crashes.download(0).crash_signature(): (0, None),
00347                           self.crashes.download(2).crash_signature(): (2, None),
00348                           self.crashes.download(3).crash_signature(): (3, '4.1'),
00349                           self.crashes.download(4).crash_signature(): (4, None)})
00350 
00351         # check with unknown fixed version
00352         self.crashes.reports[3]['fixed_version'] = ''
00353         self.crashes.duplicate_db_fixed(3, '')
00354 
00355         r = copy.copy(self.crashes.download(3))
00356         r['Package'] = 'python-goo 5.1'
00357         self.assertEqual(self.crashes.get_comment_url(r, self.crashes.upload(r)),
00358                          'http://pygoo.bugs.example.com/7')
00359         self.assertEqual(self.crashes.check_duplicate(7), (3, ''))
00360         # not marked as regression
00361         self.assertFalse('comment' in self.crashes.reports[6])
00362 
00363         # final consistency check
00364         self.assertEqual(self.crashes._duplicate_db_dump(),
00365                          {self.crashes.download(0).crash_signature(): (0, None),
00366                           self.crashes.download(2).crash_signature(): (2, None),
00367                           self.crashes.download(3).crash_signature(): (3, ''),
00368                           self.crashes.download(4).crash_signature(): (4, None)})

check_duplicate() with custom DuplicateSignature: field

Definition at line 391 of file test_crashdb.py.

00391 
00392     def test_check_duplicate_custom_signature(self):
00393         '''check_duplicate() with custom DuplicateSignature: field'''
00394 
00395         r = apport.Report()
00396         r['SourcePackage'] = 'bash'
00397         r['Package'] = 'bash 5'
00398         r['DuplicateSignature'] = 'Code42Blue'
00399         self.assertEqual(self.crashes.get_comment_url(r, self.crashes.upload(r)),
00400                          'http://bash.bugs.example.com/5')
00401 
00402         self.crashes.init_duplicate_db(':memory:')
00403         self.assertEqual(self.crashes.check_duplicate(5), None)
00404 
00405         self.assertEqual(self.crashes._duplicate_db_dump(), {'Code42Blue': (5, None)})
00406 
00407         # this one has a standard crash_signature
00408         self.assertEqual(self.crashes.check_duplicate(0), None)
00409         # ... but DuplicateSignature wins
00410         self.crashes.download(0)['DuplicateSignature'] = 'Code42Blue'
00411         self.assertEqual(self.crashes.check_duplicate(0), (5, None))
00412 
00413         self.crashes.download(1)['DuplicateSignature'] = 'CodeRed'
00414         self.assertEqual(self.crashes.check_duplicate(1), None)
00415         self.assertEqual(self.crashes._duplicate_db_dump(),
00416                          {'Code42Blue': (5, None), 'CodeRed': (1, None),
00417                           self.crashes.download(0).crash_signature(): (0, None)})

check_duplicate() with multiple master bugs

Due to the unavoidable jitter in gdb stack traces, it can happen that a
bug B has the same symbolic signature as a bug S, but the same address
signature as a bug A, where A and S have slightly different symbolic
and address signatures and thus were not identified as duplicates. In
that case we want the lowest ID to become the new master bug, and the
other two duplicates.

Definition at line 433 of file test_crashdb.py.

00433 
00434     def test_check_duplicate_multiple_masters(self):
00435         '''check_duplicate() with multiple master bugs
00436 
00437         Due to the unavoidable jitter in gdb stack traces, it can happen that a
00438         bug B has the same symbolic signature as a bug S, but the same address
00439         signature as a bug A, where A and S have slightly different symbolic
00440         and address signatures and thus were not identified as duplicates. In
00441         that case we want the lowest ID to become the new master bug, and the
00442         other two duplicates.
00443         '''
00444         a = apport.Report()
00445         a['SourcePackage'] = 'bash'
00446         a['Package'] = 'bash 5'
00447         a.crash_signature = lambda: '/bin/bash:11:read:main'
00448         a.crash_signature_addresses = lambda: '/bin/bash:11:/lib/libc.so+123:/bin/bash+DEAD'
00449         self.assertEqual(self.crashes.get_comment_url(a, self.crashes.upload(a)),
00450                          'http://bash.bugs.example.com/5')
00451 
00452         s = apport.Report()
00453         s['SourcePackage'] = 'bash'
00454         s['Package'] = 'bash 5'
00455         s.crash_signature = lambda: '/bin/bash:11:__getch:read:main'
00456         s.crash_signature_addresses = lambda: '/bin/bash:11:/lib/libc.so+BEEF:/lib/libc.so+123:/bin/bash+DEAD'
00457         self.assertEqual(self.crashes.get_comment_url(s, self.crashes.upload(s)),
00458                          'http://bash.bugs.example.com/6')
00459 
00460         # same addr sig as a, same symbolic sig as s
00461         b = apport.Report()
00462         b['SourcePackage'] = 'bash'
00463         b['Package'] = 'bash 5'
00464         b.crash_signature = lambda: '/bin/bash:11:__getch:read:main'
00465         b.crash_signature_addresses = lambda: '/bin/bash:11:/lib/libc.so+123:/bin/bash+DEAD'
00466         self.assertEqual(self.crashes.get_comment_url(b, self.crashes.upload(b)),
00467                          'http://bash.bugs.example.com/7')
00468 
00469         self.crashes.init_duplicate_db(':memory:')
00470         self.assertEqual(self.crashes.check_duplicate(5, a), None)
00471 
00472         # a and s have slightly different sigs -> no dupe
00473         self.assertEqual(self.crashes.check_duplicate(6, s), None)
00474 
00475         # now throw the interesting b at it
00476         self.assertEqual(self.crashes.check_duplicate(7, b), (5, None))
00477 
00478         # s and b should now be duplicates of a
00479         self.assertEqual(self.crashes.duplicate_of(5), None)
00480         self.assertEqual(self.crashes.duplicate_of(6), 5)
00481         self.assertEqual(self.crashes.duplicate_of(7), 5)
00482 
00483         # sig DB should only have a now
00484         self.assertEqual(self.crashes._duplicate_db_dump(), {'/bin/bash:11:read:main': (5, None)})
00485 
00486         # addr DB should have both possible patterns on a
00487         self.assertEqual(self.crashes._duplicate_search_address_signature(b.crash_signature_addresses()), 5)
00488         self.assertEqual(self.crashes._duplicate_search_address_signature(s.crash_signature_addresses()), 5)

check_duplicate() with explicitly passing report

Definition at line 418 of file test_crashdb.py.

00418 
00419     def test_check_duplicate_report_arg(self):
00420         '''check_duplicate() with explicitly passing report'''
00421 
00422         self.crashes.init_duplicate_db(':memory:')
00423 
00424         # ID#0 -> no dup
00425         self.assertEqual(self.crashes.check_duplicate(0), None)
00426 
00427         # ID#2 is unrelated, no dup
00428         self.assertEqual(self.crashes.check_duplicate(2), None)
00429 
00430         # report from ID#1 is a dup of #0
00431         self.assertEqual(self.crashes.check_duplicate(2, self.crashes.download(1)),
00432                          (0, None))

check_duplicate() with UTF-8 strings

Definition at line 369 of file test_crashdb.py.

00369 
00370     def test_check_duplicate_utf8(self):
00371         '''check_duplicate() with UTF-8 strings'''
00372 
00373         # assertion failure, with UTF-8 strings
00374         r = apport.Report()
00375         r['Package'] = 'bash 5'
00376         r['SourcePackage'] = 'bash'
00377         r['DistroRelease'] = 'Testux 2.2'
00378         r['ExecutablePath'] = '/bin/bash'
00379         r['Signal'] = '6'
00380         r['AssertionMessage'] = 'Afirmação x != 0'
00381         self.assertEqual(self.crashes.get_comment_url(r, self.crashes.upload(r)),
00382                          'http://bash.bugs.example.com/5')
00383         self.assertEqual(self.crashes.get_comment_url(r, self.crashes.upload(r)),
00384                          'http://bash.bugs.example.com/6')
00385 
00386         self.crashes.init_duplicate_db(':memory:')
00387         self.assertEqual(self.crashes.check_duplicate(5), None)
00388         self.assertEqual(self.crashes.check_duplicate(6), (5, None))
00389 
00390         self.crashes.duplicate_db_publish(self.dupdb_dir)

Detection of DB file corruption

Definition at line 666 of file test_crashdb.py.

00666 
00667     def test_db_corruption(self):
00668         '''Detection of DB file corruption'''
00669 
00670         try:
00671             (fd, db) = tempfile.mkstemp()
00672             os.close(fd)
00673             self.crashes.init_duplicate_db(db)
00674             self.assertEqual(self.crashes.check_duplicate(0), None)
00675             self.assertEqual(self.crashes._duplicate_db_dump(),
00676                              {self.crashes.download(0).crash_signature(): (0, None)})
00677             self.crashes.duplicate_db_fixed(0, '42')
00678             self.assertEqual(self.crashes._duplicate_db_dump(),
00679                              {self.crashes.download(0).crash_signature(): (0, '42')})
00680 
00681             del self.crashes
00682 
00683             # damage file
00684             f = open(db, 'r+')
00685             f.truncate(os.path.getsize(db) * 2 / 3)
00686             f.close()
00687 
00688             self.crashes = CrashDatabase(None, {})
00689             self.assertRaises(Exception, self.crashes.init_duplicate_db, db)
00690 
00691         finally:
00692             os.unlink(db)

duplicate_db_fixed()

Definition at line 214 of file test_crashdb.py.

00214 
00215     def test_duplicate_db_fixed(self):
00216         '''duplicate_db_fixed()'''
00217 
00218         self.crashes.init_duplicate_db(':memory:')
00219         self.assertEqual(self.crashes.check_duplicate(0), None)
00220 
00221         self.assertEqual(self.crashes._duplicate_db_dump(),
00222                          {self.crashes.download(0).crash_signature(): (0, None)})
00223 
00224         self.crashes.duplicate_db_fixed(0, '42')
00225 
00226         self.assertEqual(self.crashes._duplicate_db_dump(),
00227                          {self.crashes.download(0).crash_signature(): (0, '42')})

duplicate_db_publish() with very long signatures

Definition at line 612 of file test_crashdb.py.

00612 
00613     def test_duplicate_db_publish_long_sigs(self):
00614         '''duplicate_db_publish() with very long signatures'''
00615 
00616         self.crashes.init_duplicate_db(':memory:')
00617 
00618         # give #0 a long symbolic sig which needs lots of quoting
00619         symb = self.crashes.download(0)
00620         symb.crash_signature = lambda: 's+' * 1000
00621 
00622         # and #1 a long addr sig
00623         addr = self.crashes.download(1)
00624         addr.crash_signature_addresses = lambda: '0x1+/' * 1000
00625 
00626         self.assertEqual(self.crashes.known(symb), None)
00627         self.assertEqual(self.crashes.check_duplicate(0), None)
00628         self.assertEqual(self.crashes.known(addr), None)
00629         self.assertEqual(self.crashes.check_duplicate(1), None)
00630 
00631         self.crashes.duplicate_db_publish(self.dupdb_dir)
00632         self.assertEqual(self.crashes.known(symb), 'http://foo.bugs.example.com/0')
00633         self.assertEqual(self.crashes.known(addr), 'http://foo.bugs.example.com/1')

duplicate_db_remove()

Definition at line 228 of file test_crashdb.py.

00228 
00229     def test_duplicate_db_remove(self):
00230         '''duplicate_db_remove()'''
00231 
00232         # db not yet initialized
00233         self.assertRaises(AssertionError, self.crashes.check_duplicate, 0)
00234 
00235         self.crashes.init_duplicate_db(':memory:')
00236 
00237         self.assertEqual(self.crashes.check_duplicate(0), None)
00238         self.assertEqual(self.crashes.check_duplicate(2), None)
00239 
00240         # invalid ID (raising KeyError is *hard*, so it's not done)
00241         self.crashes.duplicate_db_remove(99)
00242 
00243         # nevertheless, this should not change the DB
00244         self.assertEqual(self.crashes._duplicate_db_dump(),
00245                          {self.crashes.download(0).crash_signature(): (0, None),
00246                           self.crashes.download(2).crash_signature(): (2, None)})
00247 
00248         # valid ID
00249         self.crashes.duplicate_db_remove(2)
00250 
00251         # check DB consistency
00252         self.assertEqual(self.crashes._duplicate_db_dump(),
00253                          {self.crashes.download(0).crash_signature(): (0, None)})

Dynamic code in crashdb.conf

Definition at line 44 of file test_crashdb.py.

00044 
00045     def test_dynamic_crashdb_conf(self):
00046         '''Dynamic code in crashdb.conf'''
00047 
00048         # use our dummy crashdb
00049         crashdb_conf = tempfile.NamedTemporaryFile()
00050         crashdb_conf.write(b'''default = 'testsuite'
00051 
00052 def get_dyn():
00053     return str(2 + 2)
00054 
00055 def get_dyn_name():
00056     return 'on_the' + 'fly'
00057 
00058 databases = {
00059     'testsuite': {
00060         'impl': 'memory',
00061         'dyn_option': get_dyn(),
00062     },
00063     get_dyn_name(): {
00064         'impl': 'memory',
00065         'whoami': 'dynname',
00066     }
00067 }
00068 ''')
00069         crashdb_conf.flush()
00070 
00071         db = apport.crashdb.get_crashdb(None, None, crashdb_conf.name)
00072         self.assertEqual(db.options['dyn_option'], '4')
00073         db = apport.crashdb.get_crashdb(None, 'on_thefly', crashdb_conf.name)
00074         self.assertFalse('dyn_opion' in db.options)
00075         self.assertEqual(db.options['whoami'], 'dynname')

Here is the call graph for this function:

Definition at line 121 of file test_crashdb.py.

00121 
00122     def test_get_affected_packages(self):
00123         self.assertEqual(self.crashes.get_affected_packages(0), ['foo'])
00124         self.assertEqual(self.crashes.get_affected_packages(1), ['foo'])
00125         self.assertEqual(self.crashes.get_affected_packages(2), ['bar'])
00126         self.assertEqual(self.crashes.get_affected_packages(3), ['pygoo'])

get_distro_release()

Definition at line 175 of file test_crashdb.py.

00175 
00176     def test_get_distro_release(self):
00177         '''get_distro_release()'''
00178 
00179         self.assertEqual(self.crashes.get_distro_release(0), 'FooLinux Pi/2')

known() for address signatures

Definition at line 489 of file test_crashdb.py.

00489 
00490     def test_known_address_sig(self):
00491         '''known() for address signatures'''
00492 
00493         self.crashes.init_duplicate_db(':memory:')
00494 
00495         r = apport.Report()
00496         r['SourcePackage'] = 'bash'
00497         r['Package'] = 'bash 5'
00498         r['ExecutablePath'] = '/bin/bash'
00499         r['Signal'] = '11'
00500         r['ProcMaps'] = '''
00501 00400000-004df000 r-xp 00000000 08:02 1044485                            /bin/bash
00502 7f491fa8f000-7f491fc24000 r-xp 00000000 08:02 522605                     /lib/x86_64-linux-gnu/libc-2.13.so
00503 '''
00504 
00505         r['Stacktrace'] = '''
00506 #0  0x00007f491fac5687 in kill ()
00507 #1  0x000000000042eb76 in ?? ()
00508 #2  0x00000000004324d8 in ??
00509 #3  0x00000000004707e3 in parse_and_execute ()
00510 #4  0x000000000041d703 in _start ()
00511 '''
00512 
00513         self.assertNotEqual(r.crash_signature_addresses(), None)
00514         self.crashes.duplicate_db_publish(self.dupdb_dir)
00515         self.assertEqual(self.crashes.known(r), None)
00516         r_id = self.crashes.upload(r)
00517         self.assertEqual(self.crashes.check_duplicate(r_id), None)
00518         self.crashes.duplicate_db_publish(self.dupdb_dir)
00519         self.assertEqual(self.crashes.known(r),
00520                          self.crashes.get_comment_url(r, r_id))
00521 
00522         # another report with same address signature
00523         r2 = apport.Report()
00524         r2['SourcePackage'] = 'bash'
00525         r2['Package'] = 'bash 5'
00526         r2['ExecutablePath'] = '/bin/bash'
00527         r2['Signal'] = '11'
00528 
00529         r2['ProcMaps'] = '''
00530 00400000-004df000 r-xp 00000000 08:02 1044485                            /bin/bash
00531 5f491fa8f000-5f491fc24000 r-xp 00000000 08:02 522605                     /lib/x86_64-linux-gnu/libc-2.13.so
00532 '''
00533 
00534         r2['Stacktrace'] = '''
00535 #0  0x00005f491fac5687 in kill ()
00536 #1  0x000000000042eb76 in ?? ()
00537 #2  0x00000000004324d8 in ??
00538 #3  0x00000000004707e3 in parse_and_execute ()
00539 #4  0x000000000041d703 in _start ()
00540 '''
00541 
00542         self.assertEqual(r.crash_signature_addresses(),
00543                          r2.crash_signature_addresses())
00544 
00545         # DB knows about this already
00546         self.crashes.duplicate_db_publish(self.dupdb_dir)
00547         self.assertEqual(self.crashes.known(r2),
00548                          self.crashes.get_comment_url(r, r_id))
00549 
00550         # if it gets uploaded anyway, duplicate it properly
00551         r2_id = self.crashes.upload(r2)
00552         self.assertEqual(self.crashes.check_duplicate(r2_id), (r_id, None))
00553 
00554         # different address signature
00555         r3 = apport.Report()
00556         r3['SourcePackage'] = 'bash'
00557         r3['Package'] = 'bash 5'
00558         r3['ExecutablePath'] = '/bin/bash'
00559         r3['Signal'] = '11'
00560 
00561         r3['ProcMaps'] = '''
00562 00400000-004df000 r-xp 00000000 08:02 1044485                            /bin/bash
00563 5f491fa8f000-5f491fc24000 r-xp 00000000 08:02 522605                     /lib/x86_64-linux-gnu/libc-2.13.so
00564 '''
00565 
00566         r3['Stacktrace'] = '''
00567 #0  0x00005f491fac5687 in kill ()
00568 #1  0x000000000042eb76 in ?? ()
00569 #2  0x0000000000432401 in ??
00570 #3  0x00000000004707e3 in parse_and_execute ()
00571 #4  0x000000000041d703 in _start ()
00572 '''
00573         self.assertNotEqual(r.crash_signature_addresses(),
00574                             r3.crash_signature_addresses())
00575         self.crashes.duplicate_db_publish(self.dupdb_dir)
00576         self.assertEqual(self.crashes.known(r3), None)
00577 
00578         # pretend that we went through retracing and r and r3 are actually
00579         # dupes; temporarily add a signature here to convince check_duplicate()
00580         self.crashes.init_duplicate_db(':memory:')
00581         r['DuplicateSignature'] = 'moo'
00582         r3['DuplicateSignature'] = 'moo'
00583         r_id = self.crashes.upload(r)
00584         self.assertEqual(self.crashes.check_duplicate(r_id), None)
00585         r3_id = self.crashes.upload(r3)
00586         self.assertEqual(self.crashes.check_duplicate(r3_id), (r_id, None))
00587         del r['DuplicateSignature']
00588         del r3['DuplicateSignature']
00589 
00590         # now both r and r3 address sigs should be known as r_id
00591         self.crashes.duplicate_db_publish(self.dupdb_dir)
00592         self.assertEqual(self.crashes.known(r),
00593                          self.crashes.get_comment_url(r, r_id))
00594         self.assertEqual(self.crashes.known(r3),
00595                          self.crashes.get_comment_url(r3, r_id))
00596 
00597         # changing ID also works on address signatures
00598         self.crashes.duplicate_db_change_master_id(r_id, r3_id)
00599         self.crashes.duplicate_db_publish(self.dupdb_dir)
00600         self.assertEqual(self.crashes.known(r),
00601                          self.crashes.get_comment_url(r, r3_id))
00602         self.assertEqual(self.crashes.known(r3),
00603                          self.crashes.get_comment_url(r3, r3_id))
00604 
00605         # removing an ID also works for address signatures
00606         self.crashes.duplicate_db_remove(r3_id)
00607         self.crashes.duplicate_db_publish(self.dupdb_dir)
00608         self.assertEqual(self.crashes.known(r), None)
00609         self.assertEqual(self.crashes.known(r3), None)
00610 
00611         self.assertEqual(self.crashes._duplicate_db_dump(), {})

mark_regression()

Definition at line 199 of file test_crashdb.py.

00199 
00200     def test_mark_regression(self):
00201         '''mark_regression()'''
00202 
00203         self.crashes.reports[3]['fixed_version'] = '4.1'
00204 
00205         self.crashes.mark_regression(4, 3)
00206         self.assertEqual(self.crashes.reports[4]['comment'],
00207                          'regression, already fixed in #3')
00208         self.assertEqual(self.crashes.duplicate_of(3), None)
00209         self.assertEqual(self.crashes.duplicate_of(4), None)

No dummy data is added by default

Definition at line 31 of file test_crashdb.py.

00031 
00032     def test_no_dummy_data(self):
00033         '''No dummy data is added by default'''
00034 
00035         self.crashes = CrashDatabase(None, {})
00036         self.assertEqual(self.crashes.latest_id(), -1)
00037         self.assertRaises(IndexError, self.crashes.download, 0)

Bookkeeping in retraced and dupchecked bugs

Definition at line 38 of file test_crashdb.py.

00038 
00039     def test_retrace_markers(self):
00040         '''Bookkeeping in retraced and dupchecked bugs'''
00041 
00042         self.assertEqual(self.crashes.get_unretraced(), set([0, 1, 2]))
00043         self.assertEqual(self.crashes.get_dup_unchecked(), set([3, 4]))

get_unfixed(), get_fixed_version(), duplicate_of(), close_duplicate()

Definition at line 180 of file test_crashdb.py.

00180 
00181     def test_status(self):
00182         '''get_unfixed(), get_fixed_version(), duplicate_of(), close_duplicate()'''
00183 
00184         self.assertEqual(self.crashes.get_unfixed(), set([0, 1, 2, 3, 4]))
00185         self.assertEqual(self.crashes.get_fixed_version(0), None)
00186         self.assertEqual(self.crashes.get_fixed_version(1), None)
00187         self.assertEqual(self.crashes.get_fixed_version(3), None)
00188 
00189         self.assertEqual(self.crashes.duplicate_of(0), None)
00190         self.assertEqual(self.crashes.duplicate_of(1), None)
00191         self.crashes.close_duplicate({}, 1, 0)
00192         self.assertEqual(self.crashes.duplicate_of(0), None)
00193         self.assertEqual(self.crashes.duplicate_of(1), 0)
00194 
00195         self.assertEqual(self.crashes.get_unfixed(), set([0, 2, 3, 4]))
00196         self.assertEqual(self.crashes.get_fixed_version(1), 'invalid')
00197 
00198         self.assertEqual(self.crashes.get_fixed_version(99), 'invalid')

Crash uploading and downloading

Definition at line 110 of file test_crashdb.py.

00110 
00111     def test_submit(self):
00112         '''Crash uploading and downloading'''
00113 
00114         # setUp() already checks upload() and get_comment_url()
00115         r = self.crashes.download(0)
00116         self.assertEqual(r['SourcePackage'], 'foo')
00117         self.assertEqual(r['Package'], 'libfoo1 1.2-3')
00118         self.assertEqual(self.crashes.reports[0]['dup_of'], None)
00119 
00120         self.assertRaises(IndexError, self.crashes.download, 5)

update()

Definition at line 127 of file test_crashdb.py.

00127 
00128     def test_update(self):
00129         '''update()'''
00130 
00131         r = apport.Report()
00132         r['Package'] = 'new'
00133         r['FooBar'] = 'Bogus'
00134         r['StacktraceTop'] = 'Fresh!'
00135 
00136         self.crashes.update(1, r, 'muhaha')
00137         self.assertEqual(self.crashes.reports[1]['comment'], 'muhaha')
00138         self.assertEqual(self.crashes.download(1)['Package'], 'new')
00139         self.assertEqual(self.crashes.download(1)['StacktraceTop'], 'Fresh!')
00140         self.assertEqual(self.crashes.download(1)['FooBar'], 'Bogus')
00141 
00142         self.assertRaises(IndexError, self.crashes.update, 5, None, '')

update() with key_filter

Definition at line 143 of file test_crashdb.py.

00143 
00144     def test_update_filter(self):
00145         '''update() with key_filter'''
00146 
00147         r = apport.Report()
00148         r['Package'] = 'new'
00149         r['FooBar'] = 'Bogus'
00150         r['StacktraceTop'] = 'Fresh!'
00151 
00152         self.crashes.update(1, r, 'muhaha', key_filter=['FooBar', 'StacktraceTop'])
00153         self.assertEqual(self.crashes.reports[1]['comment'], 'muhaha')
00154         self.assertEqual(self.crashes.download(1)['Package'], 'libfoo1 1.2-4')
00155         self.assertEqual(self.crashes.download(1)['StacktraceTop'], 'Fresh!')
00156         self.assertEqual(self.crashes.download(1)['FooBar'], 'Bogus')
00157 
00158         self.assertRaises(IndexError, self.crashes.update, 5, None, '')

update_traces()

Definition at line 159 of file test_crashdb.py.

00159 
00160     def test_update_traces(self):
00161         '''update_traces()'''
00162 
00163         r = apport.Report()
00164         r['Package'] = 'new'
00165         r['FooBar'] = 'Bogus'
00166         r['StacktraceTop'] = 'Fresh!'
00167 
00168         self.crashes.update_traces(1, r, 'muhaha')
00169         self.assertEqual(self.crashes.reports[1]['comment'], 'muhaha')
00170         self.assertEqual(self.crashes.download(1)['Package'], 'libfoo1 1.2-4')
00171         self.assertEqual(self.crashes.download(1)['StacktraceTop'], 'Fresh!')
00172         self.assertFalse('FooBar' in self.crashes.download(1))
00173 
00174         self.assertRaises(IndexError, self.crashes.update_traces, 5, None)


Member Data Documentation

Definition at line 12 of file test_crashdb.py.

Definition at line 11 of file test_crashdb.py.

Definition at line 10 of file test_crashdb.py.


The documentation for this class was generated from the following file: