def test_apport_bug_package_layout_load_file(self): '''bug layout from a loaded report''' self.app.report_file = '/tmp/foo.apport' self.app.report = apport.Report('Bug') self.app.report['Package'] = 'libfoo1' self.app.report['SourcePackage'] = 'foo' GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual( self.app.w('title_label').get_text(), _('Send problem report to the developers?')) self.assertFalse(self.app.w('subtitle_label').get_property('visible')) send_error_report = self.app.w('send_error_report') self.assertFalse(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertFalse(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Send')) self.assertFalse(self.app.w('closed_button').get_property('visible')) self.assertTrue(self.app.w('cancel_button').get_property('visible')) self.assertTrue( self.app.w('details_scrolledwindow').get_property('visible')) self.assertTrue(self.app.w('dialog_crash_new').get_resizable())
def test_package_crash_layout(self): ''' +-----------------------------------------------------------------+ | [ error ] Sorry, a problem occurred while installing software. | | Package: apport 1.2.3~0ubuntu1 | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Package' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0]) self.assertEqual(self.app.dialog.heading.text(), _('Sorry, a problem occurred while installing software.')) self.assertTrue(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertTrue(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Continue')) self.assertFalse(self.app.dialog.closed_button.isVisible()) self.assertEqual(self.app.dialog.text.text(), _('Package: apport 1.2.3~0ubuntu1'))
def test_package_crash_layout(self): ''' +-----------------------------------------------------------------+ | [ error ] Sorry, a problem occurred while installing software. | | Package: apport 1.2.3~0ubuntu1 | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Package' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0]) self.assertEqual( self.app.dialog.heading.text(), _('Sorry, a problem occurred while installing software.')) self.assertTrue(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertTrue(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Continue')) self.assertFalse(self.app.dialog.closed_button.isVisible()) self.assertEqual(self.app.dialog.text.text(), _('Package: apport 1.2.3~0ubuntu1'))
def test_regular_crash_layout_norestart(self): ''' +-----------------------------------------------------------------+ | [ apport ] The application Apport has closed unexpectedly. | | | | [x] Send an error report to help fix this problem. | | [ ] Ignore future problems of this program version. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' # pretend we did not get called through run_crashes(), thus no offer_restart self.app.report['ProblemType'] = 'Crash' self.app.report['CrashCounter'] = '1' self.app.report['ProcCmdline'] = 'apport-bug apport' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' with tempfile.NamedTemporaryFile() as fp: fp.write(b'''[Desktop Entry] Version=1.0 Name=Apport Type=Application''') fp.flush() self.app.report['DesktopFile'] = fp.name GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual( self.app.w('dialog_crash_new').get_title(), self.distro) self.assertEqual( self.app.w('title_label').get_text(), _('The application Apport has closed unexpectedly.')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual( self.app.w('continue_button').get_label(), _('Continue')) self.assertFalse(self.app.w('closed_button').get_property('visible'))
def test_kernel_crash_layout(self): ''' +-----------------------------------------------------------------+ | [ logo] YourDistro has experienced an internal error. | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'KernelCrash' GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('dialog_crash_new').get_title(), self.distro) self.assertEqual(self.app.w('title_label').get_text(), _('Sorry, %s has experienced an internal error.') % self.distro) send_error_report = self.app.w('send_error_report') self.assertTrue(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertTrue(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Continue')) self.assertFalse(self.app.w('closed_button').get_property('visible')) self.assertFalse(self.app.w('subtitle_label').get_property('visible')) self.assertFalse(self.app.w('ignore_future_problems').get_property('visible'))
def test_package_crash_layout(self): ''' +-----------------------------------------------------------------+ | [ error ] Sorry, a problem occurred while installing software. | | Package: apport 1.2.3~0ubuntu1 | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Package' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('dialog_crash_new').get_title(), self.distro) self.assertEqual(self.app.w('title_label').get_text(), _('Sorry, a problem occurred while installing software.')) send_error_report = self.app.w('send_error_report') self.assertTrue(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertTrue(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Continue')) self.assertFalse(self.app.w('closed_button').get_property('visible')) self.assertTrue(self.app.w('subtitle_label').get_property('visible')) self.assertEqual(self.app.w('subtitle_label').get_text(), _('Package: apport 1.2.3~0ubuntu1'))
def test_apport_bug_package_layout(self): ''' +-------------------------------------------------------------------+ | [ error ] Send problem report to the developers? | | | | +----------------------------------------------------+ | | | |> ApportVersion | | | | ... | | | +----------------------------------------------------+ | | | | [ Cancel ] [ Send ] | +-------------------------------------------------------------------+ ''' self.app.report_file = None QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0]) self.assertEqual(self.app.dialog.heading.text(), _('Send problem report to the developers?')) self.assertFalse(self.app.dialog.text.isVisible()) self.assertFalse(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertFalse(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Send')) self.assertFalse(self.app.dialog.closed_button.isVisible()) self.assertTrue(self.app.dialog.cancel_button.isVisible()) self.assertTrue(self.app.dialog.treeview.isVisible())
def test_system_crash_layout(self): ''' +-----------------------------------------------------------------+ | [ logo ] Sorry, YourDistro has experienced an internal error. | | If you notice further problems, try restarting the | | computer | | | | [x] Send an error report to help fix this problem. | | [ ] Ignore future problems of this type. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Crash' self.app.report['CrashCounter'] = '1' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0]) self.assertEqual(self.app.dialog.heading.text(), _('Sorry, %s has experienced an internal error.') % self.distro) self.assertEqual(self.app.dialog.text.text(), _('If you notice further problems, try restarting the computer.')) self.assertTrue(self.app.dialog.text.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertTrue(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Continue')) self.assertFalse(self.app.dialog.closed_button.isVisible()) self.assertTrue(self.app.dialog.ignore_future_problems.isVisible()) self.assertTrue(str(self.app.dialog.ignore_future_problems.text()).endswith( 'of this type'))
def test_system_crash_layout(self): ''' +---------------------------------------------------------------+ | [ logo ] Sorry, YourDistro has experienced an internal error. | | If you notice further problems, try restarting the | | computer | | | | [x] Send an error report to help fix this problem. | | [ ] Ignore future problems of this type. | | | | [ Show Details ] [ Continue ] | +---------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Crash' self.app.report['CrashCounter'] = '1' self.app.report['Package'] = 'bash 5' GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('dialog_crash_new').get_title(), self.distro) self.assertEqual(self.app.w('title_label').get_text(), _('Sorry, %s has experienced an internal error.') % self.distro) self.assertEqual(self.app.w('subtitle_label').get_text(), _('If you notice further problems, try restarting the computer.')) self.assertTrue(self.app.w('subtitle_label').get_property('visible')) send_error_report = self.app.w('send_error_report') self.assertTrue(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertTrue(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Continue')) self.assertFalse(self.app.w('closed_button').get_property('visible')) self.assertTrue(self.app.w('ignore_future_problems').get_property('visible')) self.assertTrue(self.app.w('ignore_future_problems').get_label().endswith( 'of this type'))
def test_apport_bug_package_layout(self): ''' +-------------------------------------------------------------------+ | [ error ] Send problem report to the developers? | | | | +----------------------------------------------------+ | | | |> ApportVersion | | | | ... | | | +----------------------------------------------------+ | | | | [ Cancel ] [ Send ] | +-------------------------------------------------------------------+ ''' self.app.report_file = None GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('title_label').get_text(), _('Send problem report to the developers?')) self.assertFalse(self.app.w('subtitle_label').get_property('visible')) send_error_report = self.app.w('send_error_report') self.assertFalse(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertFalse(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Send')) self.assertFalse(self.app.w('closed_button').get_property('visible')) self.assertTrue(self.app.w('cancel_button').get_property('visible')) self.assertTrue(self.app.w('details_scrolledwindow').get_property('visible')) self.assertTrue(self.app.w('dialog_crash_new').get_resizable())
def test_regular_crash_layout_norestart(self): ''' +-----------------------------------------------------------------+ | [ apport ] The application Apport has closed unexpectedly. | | | | [x] Send an error report to help fix this problem. | | [ ] Ignore future problems of this program version. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' # pretend we did not get called through run_crashes(), thus no offer_restart self.app.report['ProblemType'] = 'Crash' self.app.report['CrashCounter'] = '1' self.app.report['ProcCmdline'] = 'apport-bug apport' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' with tempfile.NamedTemporaryFile() as fp: fp.write(b'''[Desktop Entry] Version=1.0 Name=Apport Type=Application''') fp.flush() self.app.report['DesktopFile'] = fp.name QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.heading.text(), _('The application Apport has closed unexpectedly.')) self.assertTrue(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertTrue(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Continue')) self.assertFalse(self.app.dialog.closed_button.isVisible())
def test_system_crash_from_console_layout(self): ''' +-------------------------------------------------------------------+ | [ ubuntu ] Sorry, the application apport has closed unexpectedly. | | If you notice further problems, try restarting the | | computer | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Continue ] | +-------------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Crash' self.app.report['Package'] = 'bash 5' self.app.report['ProcEnviron'] = ('LANGUAGE=en_GB:en\n' 'SHELL=/bin/sh\n' 'TERM=xterm') self.app.report['ExecutablePath'] = '/usr/bin/apport' # This will be set by apport/ui.py in load_report() self.app.cur_package = 'apport' GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual( self.app.w('dialog_crash_new').get_title(), self.distro) self.assertEqual( self.app.w('title_label').get_text(), _('Sorry, the application apport has stopped unexpectedly.')) self.assertEqual( self.app.w('subtitle_label').get_text(), _('If you notice further problems, try restarting the computer.')) self.assertTrue(self.app.w('subtitle_label').get_property('visible')) send_error_report = self.app.w('send_error_report') self.assertTrue(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertTrue(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual( self.app.w('continue_button').get_label(), _('Continue')) self.assertFalse(self.app.w('closed_button').get_property('visible')) del self.app.report['ExecutablePath'] GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual( self.app.w('title_label').get_text(), _('Sorry, apport has closed unexpectedly.')) # no crash counter self.assertFalse( self.app.w('ignore_future_problems').get_property('visible'))
def test_hang_layout(self): ''' +-----------------------------------------------------------------+ | [ apport ] The application Apport has stopped responding. | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Force Closed ] [ Relaunch ] | +-----------------------------------------------------------------+ ''' # pretend we got called through run_crashes() which sets offer_restart self.app.offer_restart = True self.app.report['ProblemType'] = 'Hang' self.app.report['ProcCmdline'] = 'apport-bug apport' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' with tempfile.NamedTemporaryFile() as fp: fp.write(b'''[Desktop Entry] Version=1.0 Name=Apport Type=Application''') fp.flush() self.app.report['DesktopFile'] = fp.name GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual( self.app.w('dialog_crash_new').get_title(), self.distro) self.assertEqual( self.app.w('title_label').get_text(), _('The application Apport has stopped responding.')) self.assertEqual( self.app.w('subtitle_label').get_text(), _('You can wait to see if it wakes up, or close or ' 'relaunch it.')) send_error_report = self.app.w('send_error_report') self.assertTrue(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertTrue(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual( self.app.w('continue_button').get_label(), _('Relaunch')) self.assertTrue(self.app.w('closed_button').get_property('visible')) self.assertEqual( self.app.w('closed_button').get_label(), _('Force Closed')) self.assertTrue(self.app.w('subtitle_label').get_property('visible')) self.assertFalse( self.app.w('ignore_future_problems').get_property('visible'))
def test_system_crash_from_console_layout(self): ''' +-------------------------------------------------------------------+ | [ ubuntu ] Sorry, the application apport has closed unexpectedly. | | If you notice further problems, try restarting the | | computer | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Continue ] | +-------------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Crash' self.app.report['Package'] = 'bash 5' self.app.report['ProcEnviron'] = ('LANGUAGE=en_GB:en\n' 'SHELL=/bin/sh\n' 'TERM=xterm') self.app.report['ExecutablePath'] = '/usr/bin/apport' # This will be set by apport/ui.py in load_report() self.app.cur_package = 'apport' GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('dialog_crash_new').get_title(), self.distro) self.assertEqual(self.app.w('title_label').get_text(), _('Sorry, the application apport has closed unexpectedly.')) self.assertEqual(self.app.w('subtitle_label').get_text(), _('If you notice further problems, try restarting the computer.')) self.assertTrue(self.app.w('subtitle_label').get_property('visible')) send_error_report = self.app.w('send_error_report') self.assertTrue(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertTrue(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Continue')) self.assertFalse(self.app.w('closed_button').get_property('visible')) del self.app.report['ExecutablePath'] GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('title_label').get_text(), _('Sorry, apport has closed unexpectedly.')) # no crash counter self.assertFalse(self.app.w('ignore_future_problems').get_property('visible'))
def test_regular_crash_thread_layout(self): '''A thread of execution has failed, but the application persists.''' self.app.report['ProblemType'] = 'Crash' self.app.report['ProcStatus'] = 'Name:\tupstart\nPid:\t1' GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertFalse(self.app.w('closed_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Continue'))
def test_regular_crash_thread_layout(self): '''A thread of execution has failed, but the application persists.''' self.app.report['ProblemType'] = 'Crash' self.app.report['ProcStatus'] = 'Name:\tupstart\nPid:\t1' QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertFalse(self.app.dialog.closed_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Continue'))
def test_hang_layout(self): ''' +-----------------------------------------------------------------+ | [ apport ] The application Apport has stopped responding. | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Force Closed ] [ Relaunch ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Hang' self.app.report['ProcCmdline'] = 'apport-bug apport' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' with tempfile.NamedTemporaryFile() as fp: fp.write(b'''[Desktop Entry] Version=1.0 Name=Apport Type=Application''') fp.flush() self.app.report['DesktopFile'] = fp.name GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('dialog_crash_new').get_title(), self.distro) self.assertEqual(self.app.w('title_label').get_text(), _('The application Apport has stopped responding.')) self.assertEqual(self.app.w('subtitle_label').get_text(), _('You can wait to see if it wakes up, or close or ' 'relaunch it.')) send_error_report = self.app.w('send_error_report') self.assertTrue(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertTrue(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Relaunch')) self.assertTrue(self.app.w('closed_button').get_property('visible')) self.assertEqual(self.app.w('closed_button').get_label(), _('Force Closed')) self.assertTrue(self.app.w('subtitle_label').get_property('visible')) self.assertFalse(self.app.w('ignore_future_problems').get_property('visible'))
def test_regular_crash_layout_restart(self): ''' +-----------------------------------------------------------------+ | [ apport ] The application Apport has closed unexpectedly. | | | | [x] Send an error report to help fix this problem. | | [ ] Ignore future problems of this program version. | | | | [ Show Details ] [ Leave Closed ] [ Relaunch ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Crash' self.app.report['CrashCounter'] = '1' self.app.report['ProcCmdline'] = 'apport-bug apport' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' with tempfile.NamedTemporaryFile() as fp: fp.write('''[Desktop Entry] Version=1.0 Name=Apport Type=Application''') fp.flush() self.app.report['DesktopFile'] = fp.name GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('dialog_crash_new').get_title(), self.distro) self.assertEqual(self.app.w('title_label').get_text(), _('The application Apport has closed unexpectedly.')) send_error_report = self.app.w('send_error_report') self.assertTrue(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertTrue(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Relaunch')) self.assertTrue(self.app.w('closed_button').get_property('visible')) self.assertFalse(self.app.w('subtitle_label').get_property('visible')) self.assertTrue(self.app.w('ignore_future_problems').get_property('visible')) self.assertTrue(self.app.w('ignore_future_problems').get_label().endswith( 'of this program version'))
def test_regular_crash_layout_restart(self): ''' +-----------------------------------------------------------------+ | [ apport ] The application Apport has closed unexpectedly. | | | | [x] Send an error report to help fix this problem. | | [ ] Ignore future problems of this program version. | | | | [ Show Details ] [ Leave Closed ] [ Relaunch ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Crash' self.app.report['CrashCounter'] = '1' self.app.report['ProcCmdline'] = 'apport-bug apport' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' with tempfile.NamedTemporaryFile() as fp: fp.write(b'''[Desktop Entry] Version=1.0 Name=Apport Type=Application''') fp.flush() self.app.report['DesktopFile'] = fp.name QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0]) self.assertEqual(self.app.dialog.heading.text(), _('The application Apport has closed unexpectedly.')) self.assertTrue(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertTrue(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Relaunch')) self.assertTrue(self.app.dialog.closed_button.isVisible()) self.assertFalse(self.app.dialog.text.isVisible()) self.assertFalse(self.app.dialog.text.isVisible()) self.assertTrue(self.app.dialog.ignore_future_problems.isVisible()) self.assertTrue(str(self.app.dialog.ignore_future_problems.text()).endswith( 'of this program version'))
def test_regular_crash_layout_restart(self): ''' +-----------------------------------------------------------------+ | [ apport ] The application Apport has closed unexpectedly. | | | | [x] Send an error report to help fix this problem. | | [ ] Ignore future problems of this program version. | | | | [ Show Details ] [ Leave Closed ] [ Relaunch ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Crash' self.app.report['CrashCounter'] = '1' self.app.report['ProcCmdline'] = 'apport-bug apport' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' with tempfile.NamedTemporaryFile() as fp: fp.write(b'''[Desktop Entry] Version=1.0 Name=Apport Type=Application''') fp.flush() self.app.report['DesktopFile'] = fp.name QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0]) self.assertEqual(self.app.dialog.heading.text(), _('The application Apport has closed unexpectedly.')) self.assertTrue(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertTrue(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Relaunch')) self.assertTrue(self.app.dialog.closed_button.isVisible()) self.assertFalse(self.app.dialog.text.isVisible()) self.assertFalse(self.app.dialog.text.isVisible()) self.assertTrue(self.app.dialog.ignore_future_problems.isVisible()) self.assertTrue( str(self.app.dialog.ignore_future_problems.text()).endswith( 'of this program version'))
def test_regular_crash_layout_restart(self): ''' +-----------------------------------------------------------------+ | [ apport ] The application Apport has closed unexpectedly. | | | | [x] Send an error report to help fix this problem. | | [ ] Ignore future problems of this program version. | | | | [ Show Details ] [ Leave Closed ] [ Relaunch ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Crash' self.app.report['CrashCounter'] = '1' self.app.report['ProcCmdline'] = 'apport-bug apport' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' with tempfile.NamedTemporaryFile() as fp: fp.write(b'''[Desktop Entry] Version=1.0 Name=Apport Type=Application''') fp.flush() self.app.report['DesktopFile'] = fp.name GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('dialog_crash_new').get_title(), self.distro) self.assertEqual(self.app.w('title_label').get_text(), _('The application Apport has closed unexpectedly.')) send_error_report = self.app.w('send_error_report') self.assertTrue(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertTrue(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Relaunch')) self.assertTrue(self.app.w('closed_button').get_property('visible')) self.assertFalse(self.app.w('subtitle_label').get_property('visible')) self.assertTrue(self.app.w('ignore_future_problems').get_property('visible')) self.assertTrue(self.app.w('ignore_future_problems').get_label().endswith( 'of this program version'))
def test_kernel_crash_layout(self): ''' +-----------------------------------------------------------------+ | [ logo ] YourDistro has experienced an internal error. | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'KernelCrash' QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0]) self.assertEqual(self.app.dialog.heading.text(), _('Sorry, %s has experienced an internal error.') % self.distro) self.assertTrue(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertTrue(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Continue')) self.assertFalse(self.app.dialog.closed_button.isVisible()) self.assertFalse(self.app.dialog.text.isVisible())
def test_apport_bug_package_layout_load_file(self): '''bug layout from a loaded report''' self.app.report_file = '/tmp/foo.apport' self.app.report = apport.Report('Bug') self.app.report['Package'] = 'libfoo1' self.app.report['SourcePackage'] = 'foo' GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('title_label').get_text(), _('Send problem report to the developers?')) self.assertFalse(self.app.w('subtitle_label').get_property('visible')) send_error_report = self.app.w('send_error_report') self.assertFalse(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertFalse(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Send')) self.assertFalse(self.app.w('closed_button').get_property('visible')) self.assertTrue(self.app.w('cancel_button').get_property('visible')) self.assertTrue(self.app.w('details_scrolledwindow').get_property('visible')) self.assertTrue(self.app.w('dialog_crash_new').get_resizable())
def test_kernel_crash_layout(self): ''' +-----------------------------------------------------------------+ | [ logo ] YourDistro has experienced an internal error. | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'KernelCrash' QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0]) self.assertEqual( self.app.dialog.heading.text(), _('Sorry, %s has experienced an internal error.') % self.distro) self.assertTrue(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertTrue(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Continue')) self.assertFalse(self.app.dialog.closed_button.isVisible()) self.assertFalse(self.app.dialog.text.isVisible())
def test_system_crash_layout(self): ''' +-----------------------------------------------------------------+ | [ logo ] Sorry, YourDistro has experienced an internal error. | | If you notice further problems, try restarting the | | computer | | | | [x] Send an error report to help fix this problem. | | [ ] Ignore future problems of this type. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'Crash' self.app.report['CrashCounter'] = '1' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0]) self.assertEqual( self.app.dialog.heading.text(), _('Sorry, %s has experienced an internal error.') % self.distro) self.assertEqual( self.app.dialog.text.text(), _('If you notice further problems, try restarting the computer.')) self.assertTrue(self.app.dialog.text.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertTrue(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Continue')) self.assertFalse(self.app.dialog.closed_button.isVisible()) self.assertTrue(self.app.dialog.ignore_future_problems.isVisible()) self.assertTrue( str(self.app.dialog.ignore_future_problems.text()).endswith( 'of this type'))
def test_recoverable_crash_layout(self): ''' +-----------------------------------------------------------------+ | [ logo ] The application Foo has experienced an internal error. | | Developer-specified error text. | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'RecoverableProblem' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' self.app.report['DialogBody'] = 'Some developer-specified error text.' with tempfile.NamedTemporaryFile() as fp: fp.write(b'''[Desktop Entry] Version=1.0 Name=Apport Type=Application''') fp.flush() self.app.report['DesktopFile'] = fp.name GLib.idle_add(Gtk.main_quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.w('dialog_crash_new').get_title(), self.distro) msg = 'The application Apport has experienced an internal error.' self.assertEqual(self.app.w('title_label').get_text(), msg) msg = 'Some developer-specified error text.' self.assertEqual(self.app.w('subtitle_label').get_text(), msg) self.assertTrue(self.app.w('subtitle_label').get_property('visible')) send_error_report = self.app.w('send_error_report') self.assertTrue(send_error_report.get_property('visible')) self.assertTrue(send_error_report.get_active()) self.assertTrue(self.app.w('show_details').get_property('visible')) self.assertTrue(self.app.w('continue_button').get_property('visible')) self.assertEqual(self.app.w('continue_button').get_label(), _('Continue')) self.assertFalse(self.app.w('closed_button').get_property('visible'))
def test_recoverable_crash_layout(self): ''' +-----------------------------------------------------------------+ | [ logo ] The application Foo has experienced an internal error. | | Developer-specified error text. | | | | [x] Send an error report to help fix this problem. | | | | [ Show Details ] [ Continue ] | +-----------------------------------------------------------------+ ''' self.app.report['ProblemType'] = 'RecoverableProblem' self.app.report['Package'] = 'apport 1.2.3~0ubuntu1' self.app.report['DialogBody'] = 'Some developer-specified error text.' with tempfile.NamedTemporaryFile() as fp: fp.write(b'''[Desktop Entry] Version=1.0 Name=Apport Type=Application''') fp.flush() self.app.report['DesktopFile'] = fp.name QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(True) self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0]) msg = 'The application Apport has experienced an internal error.' self.assertEqual(self.app.dialog.heading.text(), msg) msg = 'Some developer-specified error text.' self.assertEqual(self.app.dialog.text.text(), msg) self.assertTrue(self.app.dialog.text.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isVisible()) self.assertTrue(self.app.dialog.send_error_report.isChecked()) self.assertTrue(self.app.dialog.details.isVisible()) self.assertTrue(self.app.dialog.continue_button.isVisible()) self.assertEqual(self.app.dialog.continue_button.text(), _('Continue')) self.assertFalse(self.app.dialog.closed_button.isVisible())
def add_info(report, ui): add_release_info(report) add_kernel_info(report) add_cloud_info(report) add_proposed_info(report) # collect a condensed version of /proc/cpuinfo apport.hookutils.attach_file(report, '/proc/cpuinfo', 'ProcCpuinfo') short_cpuinfo = [] for item in reversed(report.get('ProcCpuinfo', '').split('\n')): short_cpuinfo.append(item) if item.startswith('processor\t:'): break short_cpuinfo = reversed(short_cpuinfo) report['ProcCpuinfoMinimal'] = '\n'.join(short_cpuinfo) report.pop('ProcCpuinfo') hook_errors = [k for k in report.keys() if k.startswith('HookError_')] if hook_errors: add_tag(report, 'apport-hook-error') # locally installed python versions can cause a multitude of errors if report.get('ProblemType') == 'Package' or \ 'python' in report.get('InterpreterPath', '') or \ 'python' in report.get('ExecutablePath', ''): for python in ('python', 'python3'): add_python_details('%sDetails' % python.title(), python, report) try: report['ApportVersion'] = apport.packaging.get_version('apport') except ValueError: # might happen on local installs pass if report.get('ProblemType') == 'Package': # every error report regarding a package should have package manager # version information apport.hookutils.attach_related_packages(report, ['dpkg', 'apt']) check_for_disk_error(report) # check to see if the real root on a persistent media is full if 'LiveMediaBuild' in report: st = os.statvfs('/cdrom') free_mb = st.f_bavail * st.f_frsize / 1000000 if free_mb < 10: report[ 'UnreportableReason'] = 'Your system partition has less than \ %s MB of free space available, which leads to problems using applications \ and installing updates. Please free some space.' % (free_mb) match_error_messages(report) for attachment in ['DpkgTerminalLog', 'VarLogDistupgradeApttermlog']: if attachment in report: log_file = get_attachment_contents(report, attachment) untrimmed_dpkg_log = log_file check_attachment_for_errors(report, attachment) trimmed_log = get_attachment_contents(report, attachment) trimmed_log = trimmed_log.split('\n') lines = [] for line in untrimmed_dpkg_log.splitlines(): if line not in trimmed_log: lines.append(str(line)) elif line in trimmed_log: trimmed_log.remove(line) dpkg_log_without_error = '\n'.join(lines) # crash reports from live system installer often expose target mount for f in ('ExecutablePath', 'InterpreterPath'): if f in report and report[f].startswith('/target/'): report[f] = report[f][7:] # Allow filing update-manager bugs with obsolete packages if report.get('Package', '').startswith('update-manager'): os.environ['APPORT_IGNORE_OBSOLETE_PACKAGES'] = '1' # file bugs against OEM project for modified packages if 'Package' in report: v = report['Package'].split()[1] oem_project = get_oem_project(report) if oem_project and ('common' in v or oem_project in v): report['CrashDB'] = 'canonical-oem' if 'Package' in report: package = report['Package'].split()[0] if package: apport.hookutils.attach_conffiles(report, package, ui=ui) # do not file bugs against "upgrade-system" if it is not installed (LP#404727) if package == 'upgrade-system' and 'not installed' in report['Package']: report[ 'UnreportableReason'] = 'You do not have the upgrade-system package installed. Please report package upgrade failures against the package that failed to install, or against upgrade-manager.' if 'Package' in report: package = report['Package'].split()[0] if package: apport.hookutils.attach_upstart_overrides(report, package) apport.hookutils.attach_upstart_logs(report, package) # build a duplicate signature tag for package reports if report.get('ProblemType') == 'Package': if 'DpkgTerminalLog' in report: # this was previously trimmed in check_attachment_for_errors termlog = report['DpkgTerminalLog'] elif 'VarLogDistupgradeApttermlog' in report: termlog = get_attachment_contents(report, 'VarLogDistupgradeApttermlog') else: termlog = None if termlog: (package, version) = report['Package'].split(None, 1) # for packages that run update-grub include /etc/default/grub UPDATE_BOOT = [ 'friendly-recovery', 'linux', 'memtest86+', 'plymouth', 'ubuntu-meta', 'virtualbox-ose' ] ug_failure = r'/etc/kernel/post(inst|rm)\.d/zz-update-grub exited with return code [1-9]+' mkconfig_failure = r'/usr/sbin/grub-mkconfig.*/etc/default/grub: Syntax error' if re.search(ug_failure, termlog) or re.search( mkconfig_failure, termlog): if report['SourcePackage'] in UPDATE_BOOT: apport.hookutils.attach_default_grub( report, 'EtcDefaultGrub') dupe_sig = '' dupe_sig_created = False # messages we expect to see from a package manager (LP: #1692127) pkg_mngr_msgs = re.compile( r"""^(Authenticating| De-configuring| Examining| Installing| Preparing| Processing\ triggers| Purging| Removing| Replaced| Replacing| Setting\ up| Unpacking| Would remove).* \.\.\.\s*$""", re.X) for line in termlog.split('\n'): if pkg_mngr_msgs.search(line): dupe_sig = '%s\n' % line dupe_sig_created = True continue dupe_sig += '%s\n' % line # this doesn't catch 'dpkg-divert: error' LP: #1581399 if 'dpkg: error' in dupe_sig and line.startswith(' '): if 'trying to overwrite' in line: conflict_pkg = re.search('in package (.*) ', line) if conflict_pkg and not apport.packaging.is_distro_package( conflict_pkg.group(1)): report['UnreportableReason'] = _( 'An Ubuntu package has a file conflict with a package that is not a genuine Ubuntu package.' ) add_tag(report, 'package-conflict') if dupe_sig_created: # the duplicate signature should be the first failure report['DuplicateSignature'] = 'package:%s:%s\n%s' % ( package, version, dupe_sig) break if dupe_sig: if dpkg_log_without_error.find(dupe_sig) != -1: report['UnreportableReason'] = _( 'You have already encountered this package installation failure.' )
def check_attachment_for_errors(report, attachment): if report.get('ProblemType') == 'Package': wrong_grub_msg = _('''Your system was initially configured with grub version 2, but you have removed it from your system in favor of grub 1 without configuring it. To ensure your bootloader configuration is updated whenever a new kernel is available, open a terminal and run: sudo apt-get install grub-pc ''') trim_dpkg_log(report) log_file = get_attachment_contents(report, attachment) if 'DpkgTerminalLog' in report \ and re.search(r'^Not creating /boot/grub/menu.lst as you wish', report['DpkgTerminalLog'], re.MULTILINE): grub_hook_failure = True else: grub_hook_failure = False if report['Package'] not in ['grub', 'grub2']: # linux-image postinst emits this when update-grub fails # https://wiki.ubuntu.com/KernelTeam/DebuggingUpdateErrors grub_errors = [r'^User postinst hook script \[.*update-grub\] exited with value', r'^run-parts: /etc/kernel/post(inst|rm).d/zz-update-grub exited with return code [1-9]+', r'^/usr/sbin/grub-probe: error'] for grub_error in grub_errors: if attachment in report and re.search(grub_error, log_file, re.MULTILINE): # File these reports on the grub package instead grub_package = apport.packaging.get_file_package('/usr/sbin/update-grub') if grub_package is None or grub_package == 'grub' and not 'grub-probe' in log_file: report['SourcePackage'] = 'grub' if os.path.exists('/boot/grub/grub.cfg') and grub_hook_failure: report['UnreportableReason'] = wrong_grub_msg else: report['SourcePackage'] = 'grub2' if report['Package'] != 'initramfs-tools': # update-initramfs emits this when it fails, usually invoked from the linux-image postinst # https://wiki.ubuntu.com/KernelTeam/DebuggingUpdateErrors if attachment in report and re.search(r'^update-initramfs: failed for ', log_file, re.MULTILINE): # File these reports on the initramfs-tools package instead report['SourcePackage'] = 'initramfs-tools' if report['Package'] in ['emacs22', 'emacs23', 'emacs-snapshot', 'xemacs21']: # emacs add-on packages trigger byte compilation, which might fail # we are very interested in reading the compilation log to determine # where to reassign this report to regex = r'^!! Byte-compilation for x?emacs\S+ failed!' if attachment in report and re.search(regex, log_file, re.MULTILINE): for line in log_file.split('\n'): m = re.search(r'^!! and attach the file (\S+)', line) if m: path = m.group(1) apport.hookutils.attach_file_if_exists(report, path) if report['Package'].startswith('linux-image-') and attachment in report: # /etc/kernel/*.d failures from kernel package postinst m = re.search(r'^run-parts: (/etc/kernel/\S+\.d/\S+) exited with return code \d+', log_file, re.MULTILINE) if m: path = m.group(1) package = apport.packaging.get_file_package(path) if package: report['SourcePackage'] = package report['ErrorMessage'] = m.group(0) if package == 'grub-pc' and grub_hook_failure: report['UnreportableReason'] = wrong_grub_msg else: report['UnreportableReason'] = 'This failure was caused by a program which did not originate from Ubuntu' error_message = report.get('ErrorMessage') corrupt_package = 'This failure was caused by a corrupted package download or file system corruption.' if 'failed to install/upgrade: corrupted filesystem tarfile' in report.get('Title', ''): report['UnreportableReason'] = corrupt_package if 'dependency problems - leaving unconfigured' in error_message: report['UnreportableReason'] = 'This failure is a followup error from a previous package install failure.' if 'cannot access archive' in error_message: report['UnreportableReason'] = corrupt_package if re.search(r'(failed to read|failed in write|short read) on buffer copy', error_message): report['UnreportableReason'] = corrupt_package if re.search(r'(--fsys-tarfile|dpkg-deb --control) returned error exit status 2', error_message): report['UnreportableReason'] = corrupt_package if attachment in report and re.search(r'dpkg-deb: error.*is not a debian format archive', log_file, re.MULTILINE): report['UnreportableReason'] = corrupt_package if 'is already installed and configured' in report.get('ErrorMessage', ''): # there is insufficient information in the data currently gathered # so gather more data report['SourcePackage'] = 'dpkg' report['AptdaemonVersion'] = apport.packaging.get_version('aptdaemon') apport.hookutils.attach_file_if_exists(report, '/var/log/dpkg.log', 'DpkgLog') apport.hookutils.attach_file_if_exists(report, '/var/log/apt/term.log', 'AptTermLog') # gather filenames in /var/crash to see if there is one for dpkg reports = glob('/var/crash/*') if reports: report['CrashReports'] = apport.hookutils.command_output( ['stat', '-c', '%a:%u:%g:%s:%y:%x:%n'] + reports) add_tag(report, 'already-installed')
def add_info(report, ui): add_release_info(report) add_kernel_info(report) add_cloud_info(report) add_proposed_info(report) try: report['ApportVersion'] = apport.packaging.get_version('apport') except ValueError: # might happen on local installs pass if report.get('ProblemType') == 'Package': # every error report regarding a package should have package manager # version information apport.hookutils.attach_related_packages(report, ['dpkg', 'apt']) check_for_disk_error(report) # check to see if the real root on a persistent media is full if 'LiveMediaBuild' in report: st = os.statvfs('/cdrom') free_mb = st.f_bavail * st.f_frsize / 1000000 if free_mb < 10: report['UnreportableReason'] = 'Your system partition has less than \ %s MB of free space available, which leads to problems using applications \ and installing updates. Please free some space.' % (free_mb) match_error_messages(report) for attachment in ['DpkgTerminalLog', 'VarLogDistupgradeApttermlog']: if attachment in report: log_file = get_attachment_contents(report, attachment) untrimmed_dpkg_log = log_file check_attachment_for_errors(report, attachment) trimmed_log = get_attachment_contents(report, attachment) trimmed_log = trimmed_log.split('\n') lines = [] for line in untrimmed_dpkg_log.splitlines(): if line not in trimmed_log: lines.append(line) elif line in trimmed_log: trimmed_log.remove(line) # crash reports from live system installer often expose target mount for f in ('ExecutablePath', 'InterpreterPath'): if f in report and report[f].startswith('/target/'): report[f] = report[f][7:] # Allow filing update-manager bugs with obsolete packages if report.get('Package', '').startswith('update-manager'): os.environ['APPORT_IGNORE_OBSOLETE_PACKAGES'] = '1' # file bugs against OEM project for modified packages if 'Package' in report: v = report['Package'].split()[1] oem_project = get_oem_project(report) if oem_project and ('common' in v or oem_project in v): report['CrashDB'] = 'canonical-oem' if 'Package' in report: package = report['Package'].split()[0] if package: apport.hookutils.attach_conffiles(report, package, ui=ui) # do not file bugs against "upgrade-system" if it is not installed (LP#404727) if package == 'upgrade-system' and 'not installed' in report['Package']: report['UnreportableReason'] = 'You do not have the upgrade-system package installed. Please report package upgrade failures against the package that failed to install, or against upgrade-manager.' if 'Package' in report: package = report['Package'].split()[0] if package: apport.hookutils.attach_upstart_overrides(report, package) apport.hookutils.attach_upstart_logs(report, package) # build a duplicate signature tag for package reports if report.get('ProblemType') == 'Package' and 'ErrorMessage' in report and 'Package' in report: (package, version) = report['Package'].split(None, 1) dupe_sig = 'package:%s:%s:%s' % (package, version, report['ErrorMessage']) report['DuplicateSignature'] = dupe_sig if 'DpkgTerminalLog' in report: # this was previously trimmed in check_attachment_for_errors termlog = report['DpkgTerminalLog'] elif 'VarLogDistupgradeApttermlog' in report: termlog = get_attachment_contents(report, 'VarLogDistupgradeApttermlog') else: termlog = None if termlog: # for packages that run update-grub include /etc/default/grub UPDATE_BOOT = ['friendly-recovery', 'linux', 'memtest86+', 'plymouth', 'ubuntu-meta', 'virtualbox-ose'] ug_failure = r'/etc/kernel/post(inst|rm)\.d/zz-update-grub exited with return code [1-9]+' mkconfig_failure = r'/usr/sbin/grub-mkconfig.*/etc/default/grub: Syntax error' if re.search(ug_failure, termlog) or re.search(mkconfig_failure, termlog): if report['SourcePackage'] in UPDATE_BOOT: apport.hookutils.attach_default_grub(report, 'EtcDefaultGrub') if 'trying to overwrite' in dupe_sig: conflict_pkg = re.search('in package (.*) ', dupe_sig) if conflict_pkg and not apport.packaging.is_distro_package(conflict_pkg.group(1)): report['UnreportableReason'] = _('An Ubuntu package has a file conflict with a package that is not a genuine Ubuntu package') add_tag(report, 'package-conflict')
QTimer.singleShot(200, cont) self.app.run_update_report() # no new bug reported self.assertEqual(self.app.crashdb.latest_id(), 0) # bug was updated r = self.app.crashdb.download(0) self.assertTrue('ProcEnviron' in r) self.assertTrue('DistroRelease' in r) self.assertTrue('Uname' in r) self.assertEqual(r['MachineType'], 'Laptop') # No URL in this mode self.assertEqual(self.app.open_url.call_count, 0) def test_administrator_disabled_reporting(self): QTimer.singleShot(0, QCoreApplication.quit) self.app.ui_present_report_details(False) self.assertFalse(self.app.dialog.send_error_report.isVisible()) self.assertFalse(self.app.dialog.send_error_report.isChecked()) app = QApplication(sys.argv) app.applicationName = 'apport-kde' app.applicationDisplayName = _('Apport') app.windowIcon = QIcon.fromTheme('apport') unittest.main()
def add_info(report, ui): add_release_info(report) add_kernel_info(report) add_cloud_info(report) add_proposed_info(report) try: report['ApportVersion'] = apport.packaging.get_version('apport') except ValueError: # might happen on local installs pass if report.get('ProblemType') == 'Package': # every error report regarding a package should have package manager # version information apport.hookutils.attach_related_packages(report, ['dpkg', 'apt']) check_for_disk_error(report) # check to see if the real root on a persistent media is full if 'LiveMediaBuild' in report: st = os.statvfs('/cdrom') free_mb = st.f_bavail * st.f_frsize / 1000000 if free_mb < 10: report[ 'UnreportableReason'] = 'Your system partition has less than \ %s MB of free space available, which leads to problems using applications \ and installing updates. Please free some space.' % (free_mb) match_error_messages(report) for attachment in ['DpkgTerminalLog', 'VarLogDistupgradeApttermlog']: if attachment in report: log_file = get_attachment_contents(report, attachment) untrimmed_dpkg_log = log_file check_attachment_for_errors(report, attachment) trimmed_log = get_attachment_contents(report, attachment) trimmed_log = trimmed_log.split('\n') lines = [] for line in untrimmed_dpkg_log.splitlines(): if line not in trimmed_log: lines.append(line) elif line in trimmed_log: trimmed_log.remove(line) # crash reports from live system installer often expose target mount for f in ('ExecutablePath', 'InterpreterPath'): if f in report and report[f].startswith('/target/'): report[f] = report[f][7:] # Allow filing update-manager bugs with obsolete packages if report.get('Package', '').startswith('update-manager'): os.environ['APPORT_IGNORE_OBSOLETE_PACKAGES'] = '1' # file bugs against OEM project for modified packages if 'Package' in report: v = report['Package'].split()[1] oem_project = get_oem_project(report) if oem_project and ('common' in v or oem_project in v): report['CrashDB'] = 'canonical-oem' if 'Package' in report: package = report['Package'].split()[0] if package: apport.hookutils.attach_conffiles(report, package, ui=ui) # do not file bugs against "upgrade-system" if it is not installed (LP#404727) if package == 'upgrade-system' and 'not installed' in report['Package']: report[ 'UnreportableReason'] = 'You do not have the upgrade-system package installed. Please report package upgrade failures against the package that failed to install, or against upgrade-manager.' if 'Package' in report: package = report['Package'].split()[0] if package: apport.hookutils.attach_upstart_overrides(report, package) apport.hookutils.attach_upstart_logs(report, package) # build a duplicate signature tag for package reports if report.get( 'ProblemType' ) == 'Package' and 'ErrorMessage' in report and 'Package' in report: (package, version) = report['Package'].split(None, 1) dupe_sig = 'package:%s:%s:%s' % (package, version, report['ErrorMessage']) report['DuplicateSignature'] = dupe_sig if 'DpkgTerminalLog' in report: # this was previously trimmed in check_attachment_for_errors termlog = report['DpkgTerminalLog'] elif 'VarLogDistupgradeApttermlog' in report: termlog = get_attachment_contents(report, 'VarLogDistupgradeApttermlog') else: termlog = None if termlog: # for packages that run update-grub include /etc/default/grub UPDATE_BOOT = [ 'friendly-recovery', 'linux', 'memtest86+', 'plymouth', 'ubuntu-meta', 'virtualbox-ose' ] ug_failure = r'/etc/kernel/post(inst|rm)\.d/zz-update-grub exited with return code [1-9]+' mkconfig_failure = r'/usr/sbin/grub-mkconfig.*/etc/default/grub: Syntax error' if re.search(ug_failure, termlog) or re.search( mkconfig_failure, termlog): if report['SourcePackage'] in UPDATE_BOOT: apport.hookutils.attach_default_grub( report, 'EtcDefaultGrub') if 'trying to overwrite' in dupe_sig: conflict_pkg = re.search('in package (.*) ', dupe_sig) if conflict_pkg and not apport.packaging.is_distro_package( conflict_pkg.group(1)): report['UnreportableReason'] = _( 'An Ubuntu package has a file conflict with a package that is not a genuine Ubuntu package' ) add_tag(report, 'package-conflict')
def add_info(report, ui): add_release_info(report) add_kernel_info(report) add_cloud_info(report) try: report['ApportVersion'] = apport.packaging.get_version('apport') except ValueError: # might happen on local installs pass if report.get('ProblemType') == 'Package': check_for_disk_error(report) # check to see if the real root on a persistent media is full if 'LiveMediaBuild' in report: st = os.statvfs('/cdrom') free_mb = st.f_bavail * st.f_frsize / 1000000 if free_mb < 10: report['UnreportableReason'] = 'Your system partition has less than \ %s MB of free space available, which leads to problems using applications \ and installing updates. Please free some space.' % (free_mb) match_error_messages(report) for log in ['DpkgTerminalLog', 'VarLogDistupgradeApttermlog']: if log in report: check_attachment_for_errors(report, log) wrong_grub_msg = _('''Your system was initially configured with grub version 2, but you have removed it from your system in favor of grub 1 without configuring it. To ensure your bootloader configuration is updated whenever a new kernel is available, open a terminal and run: sudo apt-get install grub-pc ''') if 'DpkgTerminalLog' in report \ and re.search(r'^Not creating /boot/grub/menu.lst as you wish', report['DpkgTerminalLog'], re.MULTILINE): grub_hook_failure = True else: grub_hook_failure = False # crash reports from live system installer often expose target mount for f in ('ExecutablePath', 'InterpreterPath'): if f in report and report[f].startswith('/target/'): report[f] = report[f][7:] # Allow filing update-manager bugs with obsolete packages if report.get('Package', '').startswith('update-manager'): os.environ['APPORT_IGNORE_OBSOLETE_PACKAGES'] = '1' # file bugs against OEM project for modified packages if 'Package' in report: v = report['Package'].split()[1] oem_project = get_oem_project(report) if oem_project and ('common' in v or oem_project in v): report['CrashDB'] = 'canonical-oem' if 'Package' in report: package = report['Package'].split()[0] if package: attach_conffiles(report, package, ui=ui) # do not file bugs against "upgrade-system" if it is not installed (LP#404727) if package == 'upgrade-system' and 'not installed' in report['Package']: report['UnreportableReason'] = 'You do not have the upgrade-system package installed. Please report package upgrade failures against the package that failed to install, or against upgrade-manager.' if 'Package' in report: package = report['Package'].split()[0] if package: attach_upstart_overrides(report, package) # build a duplicate signature tag for package reports if report.get('ProblemType') == 'Package': if 'DpkgTerminalLog' in report: termlog = report['DpkgTerminalLog'] elif 'VarLogDistupgradeApttermlog' in report: termlog = report['VarLogDistupgradeApttermlog'] else: termlog = None if termlog: dupe_sig = '' for line in termlog.split('\n'): if line.startswith('Setting up') or line.startswith('Unpacking'): dupe_sig = '%s\n' % line continue dupe_sig += '%s\n' % line if 'dpkg: error' in dupe_sig and line.startswith(' '): if 'trying to overwrite' in line: conflict_pkg = re.search('in package (.*) ', line) if conflict_pkg and not apport.packaging.is_distro_package(conflict_pkg.group(1)): report['UnreportableReason'] = _('An Ubuntu package has a file conflict with a package that is not a genuine Ubuntu package') add_tag(report, 'package-conflict') if 'Setting up' in dupe_sig or 'Unpacking' in dupe_sig: report['DuplicateSignature'] = dupe_sig # the duplicate signature should be the first failure break # running Unity? username = pwd.getpwuid(os.geteuid()).pw_name if subprocess.call(['killall', '-s0', '-u', username, 'unity-panel-service'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) == 0: add_tag(report, 'running-unity')
def check_attachment_for_errors(report, attachment): if report.get('ProblemType') == 'Package': wrong_grub_msg = _( '''Your system was initially configured with grub version 2, but you have removed it from your system in favor of grub 1 without configuring it. To ensure your bootloader configuration is updated whenever a new kernel is available, open a terminal and run: sudo apt-get install grub-pc ''') trim_dpkg_log(report) log_file = get_attachment_contents(report, attachment) if 'DpkgTerminalLog' in report \ and re.search(r'^Not creating /boot/grub/menu.lst as you wish', report['DpkgTerminalLog'], re.MULTILINE): grub_hook_failure = True else: grub_hook_failure = False if report['Package'] not in ['grub', 'grub2']: # linux-image postinst emits this when update-grub fails # https://wiki.ubuntu.com/KernelTeam/DebuggingUpdateErrors grub_errors = [ r'^User postinst hook script \[.*update-grub\] exited with value', r'^run-parts: /etc/kernel/post(inst|rm).d/zz-update-grub exited with return code [1-9]+', r'^/usr/sbin/grub-probe: error' ] for grub_error in grub_errors: if attachment in report and re.search(grub_error, log_file, re.MULTILINE): # File these reports on the grub package instead grub_package = apport.packaging.get_file_package( '/usr/sbin/update-grub') if grub_package is None or grub_package == 'grub' and not 'grub-probe' in log_file: report['SourcePackage'] = 'grub' if os.path.exists( '/boot/grub/grub.cfg') and grub_hook_failure: report['UnreportableReason'] = wrong_grub_msg else: report['SourcePackage'] = 'grub2' if report['Package'] != 'initramfs-tools': # update-initramfs emits this when it fails, usually invoked from the linux-image postinst # https://wiki.ubuntu.com/KernelTeam/DebuggingUpdateErrors if attachment in report and re.search( r'^update-initramfs: failed for ', log_file, re.MULTILINE): # File these reports on the initramfs-tools package instead report['SourcePackage'] = 'initramfs-tools' if report['Package'] in [ 'emacs22', 'emacs23', 'emacs-snapshot', 'xemacs21' ]: # emacs add-on packages trigger byte compilation, which might fail # we are very interested in reading the compilation log to determine # where to reassign this report to regex = r'^!! Byte-compilation for x?emacs\S+ failed!' if attachment in report and re.search(regex, log_file, re.MULTILINE): for line in log_file.split('\n'): m = re.search(r'^!! and attach the file (\S+)', line) if m: path = m.group(1) apport.hookutils.attach_file_if_exists(report, path) if report['Package'].startswith( 'linux-image-') and attachment in report: # /etc/kernel/*.d failures from kernel package postinst m = re.search( r'^run-parts: (/etc/kernel/\S+\.d/\S+) exited with return code \d+', log_file, re.MULTILINE) if m: path = m.group(1) package = apport.packaging.get_file_package(path) if package: report['SourcePackage'] = package report['ErrorMessage'] = m.group(0) if package == 'grub-pc' and grub_hook_failure: report['UnreportableReason'] = wrong_grub_msg else: report[ 'UnreportableReason'] = 'This failure was caused by a program which did not originate from Ubuntu' error_message = report.get('ErrorMessage') corrupt_package = 'This failure was caused by a corrupted package download or file system corruption.' if 'failed to install/upgrade: corrupted filesystem tarfile' in report.get( 'Title', ''): report['UnreportableReason'] = corrupt_package if 'dependency problems - leaving unconfigured' in error_message: report[ 'UnreportableReason'] = 'This failure is a followup error from a previous package install failure.' if 'cannot access archive' in error_message: report['UnreportableReason'] = corrupt_package if re.search( r'(failed to read|failed in write|short read) on buffer copy', error_message): report['UnreportableReason'] = corrupt_package if re.search( r'(--fsys-tarfile|dpkg-deb --control) returned error exit status 2', error_message): report['UnreportableReason'] = corrupt_package if attachment in report and re.search( r'dpkg-deb: error.*is not a debian format archive', log_file, re.MULTILINE): report['UnreportableReason'] = corrupt_package if 'is already installed and configured' in report.get( 'ErrorMessage', ''): # there is insufficient information in the data currently gathered # so gather more data report['SourcePackage'] = 'dpkg' report['AptdaemonVersion'] = apport.packaging.get_version( 'aptdaemon') apport.hookutils.attach_file_if_exists(report, '/var/log/dpkg.log', 'DpkgLog') apport.hookutils.attach_file_if_exists(report, '/var/log/apt/term.log', 'AptTermLog') # gather filenames in /var/crash to see if there is one for dpkg reports = glob('/var/crash/*') if reports: report['CrashReports'] = apport.hookutils.command_output( ['stat', '-c', '%a:%u:%g:%s:%y:%x:%n'] + reports) add_tag(report, 'already-installed')