Merge lp:~gary-lasker/software-center/handle-trans-cancel-lp1027209 into lp:software-center

Proposed by Gary Lasker
Status: Merged
Merged at revision: 3186
Proposed branch: lp:~gary-lasker/software-center/handle-trans-cancel-lp1027209
Merge into: lp:software-center
Diff against target: 183 lines (+94/-3)
3 files modified
softwarecenter/backend/installbackend_impl/aptd.py (+12/-0)
softwarecenter/ui/gtk3/panes/availablepane.py (+12/-1)
tests/gtk3/test_unity_launcher_integration.py (+70/-2)
To merge this branch: bzr merge lp:~gary-lasker/software-center/handle-trans-cancel-lp1027209
Reviewer Review Type Date Requested Status
Michael Vogt Needs Information
Review via email: mp+124536@code.launchpad.net

Commit message

* lp:~gary-lasker/software-center/handle-trans-cancel-lp1027209:
    - don't add an application to the Unity launcher for the case
      where an installation is cancelled (LP: #1027209)

Description of the change

This branch contains a proposed fix for bug 1027209. To test, follow the steps outlined in comment #9 in the bug, as shown below:

Follow the below steps to see the issue:
#. Open software-center
#. Click on install on a big application like wesnoth
#. Wait until the "In Progress" appears in the toplevel toolbar of s-c
#. Click on the "In Progress" button in the toolbar
#. Click on the "cancel" button of the install of the application

Result (current trunk USC): At the moment of the cancellation, the icon for the application is incorrectly added to the Unity launcher.
Expected (this branch): After a cancellation, no icon is added to the Unity launcher.

I've also included a new unit test for this bug to insure we don't regress on it.

Many thanks for your review!

To post a comment you must log in.
Revision history for this message
Michael Vogt (mvo) wrote :

On Fri, Sep 14, 2012 at 10:53:23PM -0000, Gary Lasker wrote:
> Gary Lasker has proposed merging lp:~gary-lasker/software-center/handle-trans-cancel-lp1027209 into lp:software-center.
[..]
> Follow the below steps to see the issue:
> #. Open software-center
> #. Click on install on a big application like wesnoth
> #. Wait until the "In Progress" appears in the toplevel toolbar of s-c
> #. Click on the "In Progress" button in the toolbar
> #. Click on the "cancel" button of the install of the application
>
> I've also included a new unit test for this bug to insure we don't regress on it.

Thanks for the branch and for adding a unittest (and the adding of
docstrings, always nice).

It looks fine, the only question I have is what happens if the
transaction errors, e.g. if the network gets lost during a download of
a application. Will that work as expected, i.e. not add anything to
the launcher or do we need to connect the transaction-stopped signal
for that?

[..]
> === modified file 'tests/gtk3/test_unity_launcher_integration.py'
> --- tests/gtk3/test_unity_launcher_integration.py 2012-08-30 07:45:31 +0000
> +++ tests/gtk3/test_unity_launcher_integration.py 2012-09-14 22:52:21 +0000
> @@ -60,6 +60,20 @@
> self.available_pane.backend.emit("transaction-finished",
> mock_result)
> do_events_with_sleep()
> +
> + def _simulate_install_cancellation(self, app):
> + # pretend we started an install
> + self.available_pane.backend.emit("transaction-started",
> + app.pkgname, app.appname,
> + "testid101",
> + TransactionTypes.INSTALL)
> + do_events_with_sleep()

      self.assertEqual(
            self.available_pane.unity_launcher_transaction_queue.keys(),
            ["software-center"])

> + # send the signal to cancel the install
> + mock_result = Mock()
> + mock_result.pkgname = app.pkgname
> + self.available_pane.backend.emit("transaction-cancelled",
> + mock_result)
> + do_events_with_sleep()

        self.assertEqual(
            self.available_pane.unity_launcher_transaction_queue, {})

[..]

I like the test in general, the above lines may make it even
better. To also check that the queue behaves in the right way
(i.e. stuff is added and taken out again).

Cheers,
 Michael

Revision history for this message
Michael Vogt (mvo) :
review: Needs Information
3179. By Gary Lasker

merge trunk

3180. By Gary Lasker

consolidate code to a configurable single simulate_install_events utility method

3181. By Gary Lasker

add a new unit test that ensures we do not send an application to the launcher on a transaction error (a transaction-stopped event from aptd)

Revision history for this message
Gary Lasker (gary-lasker) wrote :
Download full text (3.2 KiB)

> On Fri, Sep 14, 2012 at 10:53:23PM -0000, Gary Lasker wrote:
> > Gary Lasker has proposed merging lp:~gary-lasker/software-center/handle-
> trans-cancel-lp1027209 into lp:software-center.
> [..]
> > Follow the below steps to see the issue:
> > #. Open software-center
> > #. Click on install on a big application like wesnoth
> > #. Wait until the "In Progress" appears in the toplevel toolbar of s-c
> > #. Click on the "In Progress" button in the toolbar
> > #. Click on the "cancel" button of the install of the application
> >
> > I've also included a new unit test for this bug to insure we don't regress
> on it.
>
> Thanks for the branch and for adding a unittest (and the adding of
> docstrings, always nice).
>
> It looks fine, the only question I have is what happens if the
> transaction errors, e.g. if the network gets lost during a download of
> a application. Will that work as expected, i.e. not add anything to
> the launcher or do we need to connect the transaction-stopped signal
> for that?

Thanks! I've added a unit test for this case and and shows that the launcher call does not occur. I took the opportunity to consolodate some (now duplicated) code.

>
> [..]
> > === modified file 'tests/gtk3/test_unity_launcher_integration.py'
> > --- tests/gtk3/test_unity_launcher_integration.py 2012-08-30 07:45:31
> +0000
> > +++ tests/gtk3/test_unity_launcher_integration.py 2012-09-14 22:52:21
> +0000
> > @@ -60,6 +60,20 @@
> > self.available_pane.backend.emit("transaction-finished",
> > mock_result)
> > do_events_with_sleep()
> > +
> > + def _simulate_install_cancellation(self, app):
> > + # pretend we started an install
> > + self.available_pane.backend.emit("transaction-started",
> > + app.pkgname, app.appname,
> > + "testid101",
> > + TransactionTypes.INSTALL)
> > + do_events_with_sleep()
>
> self.assertEqual(
> self.available_pane.unity_launcher_transaction_queue.keys(),
> ["software-center"])
>
> > + # send the signal to cancel the install
> > + mock_result = Mock()
> > + mock_result.pkgname = app.pkgname
> > + self.available_pane.backend.emit("transaction-cancelled",
> > + mock_result)
> > + do_events_with_sleep()
>
> self.assertEqual(
> self.available_pane.unity_launcher_transaction_queue, {})
>
>
> [..]
>
> I like the test in general, the above lines may make it even
> better. To also check that the queue behaves in the right way
> (i.e. stuff is added and taken out again).

This diff is a little confusing to me as it appears to add code that is already in the test (in the method _simulate_install_cancellation). But I get the gist which is to check that the queue is maintained correcty. This may not be strictly necessary, however, but I'll think about it a bit more and will add this test enhancement in a separate follow-on branch in the interest of getting the current branch merged (we are close to the wire for b2 freeze...

Read more...

3182. By Gary Lasker

RED: check that the launcher item queue is empty after a transaction is completed for all types, includes a new failing unit test for when a transaction error is encountered

3183. By Gary Lasker

add a comment to better clarify the error test

3184. By Gary Lasker

GREEN: handle the transaction error case, unit test now working

Revision history for this message
Gary Lasker (gary-lasker) wrote :

Ok, I added the check for the launcher queue to be properly emptied for the various types of transaction end cases. The error case, where a "transaction-stopped" signal is emitted, needed a fix to clear the queue so I've added that as well.

Note that clearing the queue isn't strictly required as an item left there will have no ill effect (it's only functional when the corresponding package completes a successful install, and in this case it will "just word". Plus, it's not likely that many items would end up queued in here. Neverthess, it's clean and much nicer to clear it out for all cases, so it does that now.

Should be ready for re-review now. Thanks!

3185. By Gary Lasker

merge latest trunk

Revision history for this message
Michael Vogt (mvo) wrote :

On Mon, Sep 17, 2012 at 09:55:23PM -0000, Gary Lasker wrote:
> Ok, I added the check for the launcher queue to be properly emptied for the various types of transaction end cases. The error case, where a "transaction-stopped" signal is emitted, needed a fix to clear the queue so I've added that as well.
>
> Note that clearing the queue isn't strictly required as an item left there will have no ill effect (it's only functional when the corresponding package completes a successful install, and in this case it will "just word". Plus, it's not likely that many items would end up queued in here. Neverthess, it's clean and much nicer to clear it out for all cases, so it does that now.

Thanks for the updated test and code. I agree that while unlikely to
have ill effects its a good idea to clean the queue and the test will
ensure that this is the case. I like that :)

The diff is fine, the only nitpick I have is that in lines 132-138 and
161-168 the tests sets "self.expected_{pkgname,launcher_info}". Given
that the test is about not sending the signal it seems like this is
not needed, is that correct?

Cheers,
 Michael

Revision history for this message
Michael Vogt (mvo) wrote :

I removed the bits around "self.expected_{pkgname,launcher_info}" during the merge to unblock this as we want a upload soon to go in before b2 freeze.

Revision history for this message
Gary Lasker (gary-lasker) wrote :

Hi Michael, indeed, those are needed in the tests above, but not in the two new test cases. Thank you for noticing that and removing them!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'softwarecenter/backend/installbackend_impl/aptd.py'
--- softwarecenter/backend/installbackend_impl/aptd.py 2012-09-05 06:46:15 +0000
+++ softwarecenter/backend/installbackend_impl/aptd.py 2012-09-18 04:57:18 +0000
@@ -193,6 +193,10 @@
193 'transaction-stopped': (GObject.SIGNAL_RUN_FIRST,193 'transaction-stopped': (GObject.SIGNAL_RUN_FIRST,
194 GObject.TYPE_NONE,194 GObject.TYPE_NONE,
195 (GObject.TYPE_PYOBJECT,)),195 (GObject.TYPE_PYOBJECT,)),
196 # emits a TransactionFinished object
197 'transaction-cancelled': (GObject.SIGNAL_RUN_FIRST,
198 GObject.TYPE_NONE,
199 (GObject.TYPE_PYOBJECT,)),
196 # emits with a pending_transactions list object200 # emits with a pending_transactions list object
197 'transactions-changed': (GObject.SIGNAL_RUN_FIRST,201 'transactions-changed': (GObject.SIGNAL_RUN_FIRST,
198 GObject.TYPE_NONE,202 GObject.TYPE_NONE,
@@ -848,6 +852,14 @@
848 self._logger.debug("_on_transaction_finished: %s %s %s" % (852 self._logger.debug("_on_transaction_finished: %s %s %s" % (
849 trans, enum, trans.meta_data))853 trans, enum, trans.meta_data))
850854
855 # first check if there has been a cancellation of
856 # the install and fire a transaction-cancelled signal
857 # (see LP: #1027209)
858 if enum == enums.EXIT_CANCELLED:
859 result = TransactionFinishedResult(trans, False)
860 self.emit("transaction-cancelled", result)
861 return
862
851 # show error863 # show error
852 if enum == enums.EXIT_FAILED:864 if enum == enums.EXIT_FAILED:
853 # Handle invalid packages separately865 # Handle invalid packages separately
854866
=== modified file 'softwarecenter/ui/gtk3/panes/availablepane.py'
--- softwarecenter/ui/gtk3/panes/availablepane.py 2012-09-17 15:15:32 +0000
+++ softwarecenter/ui/gtk3/panes/availablepane.py 2012-09-18 04:57:18 +0000
@@ -227,8 +227,11 @@
227 self.on_transactions_changed)227 self.on_transactions_changed)
228 self.backend.connect("transaction-finished",228 self.backend.connect("transaction-finished",
229 self.on_transaction_complete)229 self.on_transaction_complete)
230 self.backend.connect("transaction-cancelled",
231 self.on_transaction_cancelled)
232 # a transaction error is treated the same as a cancellation
230 self.backend.connect("transaction-stopped",233 self.backend.connect("transaction-stopped",
231 self.on_transaction_complete)234 self.on_transaction_cancelled)
232235
233 # now we are initialized236 # now we are initialized
234 self.searchentry.set_sensitive(True)237 self.searchentry.set_sensitive(True)
@@ -392,11 +395,19 @@
392 self._update_action_bar()395 self._update_action_bar()
393396
394 def on_transaction_complete(self, backend, result):397 def on_transaction_complete(self, backend, result):
398 """ handle a transaction that has completed successfully
399 """
395 if result.pkgname in self.unity_launcher_transaction_queue:400 if result.pkgname in self.unity_launcher_transaction_queue:
396 transaction_details = (401 transaction_details = (
397 self.unity_launcher_transaction_queue.pop(result.pkgname))402 self.unity_launcher_transaction_queue.pop(result.pkgname))
398 self._add_application_to_unity_launcher(transaction_details)403 self._add_application_to_unity_launcher(transaction_details)
399404
405 def on_transaction_cancelled(self, backend, result):
406 """ handle a transaction that has been cancelled
407 """
408 if result.pkgname in self.unity_launcher_transaction_queue:
409 self.unity_launcher_transaction_queue.pop(result.pkgname)
410
400 def _register_unity_launcher_transaction_started(self, pkgname, appname,411 def _register_unity_launcher_transaction_started(self, pkgname, appname,
401 trans_id, trans_type):412 trans_id, trans_type):
402 # at the start of the transaction, we gather details for use later413 # at the start of the transaction, we gather details for use later
403414
=== modified file 'tests/gtk3/test_unity_launcher_integration.py'
--- tests/gtk3/test_unity_launcher_integration.py 2012-08-30 07:45:31 +0000
+++ tests/gtk3/test_unity_launcher_integration.py 2012-09-18 04:57:18 +0000
@@ -47,7 +47,8 @@
47 def tearDownClass(cls):47 def tearDownClass(cls):
48 cls.win.destroy()48 cls.win.destroy()
4949
50 def _simulate_install_events(self, app):50 def _simulate_install_events(self, app,
51 result_event="transaction-finished"):
51 # pretend we started an install52 # pretend we started an install
52 self.available_pane.backend.emit("transaction-started",53 self.available_pane.backend.emit("transaction-started",
53 app.pkgname, app.appname,54 app.pkgname, app.appname,
@@ -57,7 +58,7 @@
57 # send the signal to complete the install58 # send the signal to complete the install
58 mock_result = Mock()59 mock_result = Mock()
59 mock_result.pkgname = app.pkgname60 mock_result.pkgname = app.pkgname
60 self.available_pane.backend.emit("transaction-finished",61 self.available_pane.backend.emit(result_event,
61 mock_result)62 mock_result)
62 do_events_with_sleep()63 do_events_with_sleep()
6364
@@ -122,6 +123,9 @@
122 self.assertTrue(mock_send_application_to_launcher.called)123 self.assertTrue(mock_send_application_to_launcher.called)
123 args, kwargs = mock_send_application_to_launcher.call_args124 args, kwargs = mock_send_application_to_launcher.call_args
124 self._check_send_application_to_launcher_args(*args, **kwargs)125 self._check_send_application_to_launcher_args(*args, **kwargs)
126 # insure that the unity launcher transaction queue is cleared
127 self.assertEqual(
128 self.available_pane.unity_launcher_transaction_queue, {})
125129
126 @patch('softwarecenter.ui.gtk3.panes.availablepane.UnityLauncher'130 @patch('softwarecenter.ui.gtk3.panes.availablepane.UnityLauncher'
127 '.send_application_to_launcher')131 '.send_application_to_launcher')
@@ -141,6 +145,9 @@
141 self.assertTrue(mock_send_application_to_launcher.called)145 self.assertTrue(mock_send_application_to_launcher.called)
142 args, kwargs = mock_send_application_to_launcher.call_args146 args, kwargs = mock_send_application_to_launcher.call_args
143 self._check_send_application_to_launcher_args(*args, **kwargs)147 self._check_send_application_to_launcher_args(*args, **kwargs)
148 # insure that the unity launcher transaction queue is cleared
149 self.assertEqual(
150 self.available_pane.unity_launcher_transaction_queue, {})
144 151
145 @patch('softwarecenter.ui.gtk3.panes.availablepane.UnityLauncher'152 @patch('softwarecenter.ui.gtk3.panes.availablepane.UnityLauncher'
146 '.send_application_to_launcher')153 '.send_application_to_launcher')
@@ -151,6 +158,9 @@
151 test_pkgname = "software-center"158 test_pkgname = "software-center"
152 self._navigate_to_appdetails_and_install(test_pkgname)159 self._navigate_to_appdetails_and_install(test_pkgname)
153 self.assertFalse(mock_send_application_to_launcher.called)160 self.assertFalse(mock_send_application_to_launcher.called)
161 # insure that the unity launcher transaction queue is cleared
162 self.assertEqual(
163 self.available_pane.unity_launcher_transaction_queue, {})
154 164
155 @patch('softwarecenter.ui.gtk3.panes.availablepane'165 @patch('softwarecenter.ui.gtk3.panes.availablepane'
156 '.convert_desktop_file_to_installed_location')166 '.convert_desktop_file_to_installed_location')
@@ -188,6 +198,64 @@
188 # the previous call(s)198 # the previous call(s)
189 mock_send_application_to_launcher.reset_mock()199 mock_send_application_to_launcher.reset_mock()
190200
201 @patch('softwarecenter.ui.gtk3.panes.availablepane.UnityLauncher'
202 '.send_application_to_launcher')
203 def test_unity_launcher_integration_cancelled_install(self,
204 mock_send_application_to_launcher):
205 # test the automatic add to launcher enabled functionality when
206 # installing an app from the details view, and then cancelling
207 # the install (see LP: #1027209)
208 self.config.add_to_unity_launcher = True
209 test_pkgname = "software-center"
210 self.expected_pkgname = test_pkgname
211 self.expected_launcher_info = UnityLauncherInfo("software-center",
212 "softwarecenter",
213 0, 0, 0, 0, # these values are set in availablepane
214 "/usr/share/applications/ubuntu-software-center.desktop",
215 "")
216 app = Application("", test_pkgname)
217 self.available_pane.app_view.emit("application-activated",
218 app)
219 do_events()
220 self._simulate_install_events(app,
221 result_event="transaction-cancelled")
222 # ensure that we do not send the application to the launcher
223 # on a cancelled installation
224 self.assertFalse(mock_send_application_to_launcher.called)
225 # insure that the unity launcher transaction queue is cleared
226 self.assertEqual(
227 self.available_pane.unity_launcher_transaction_queue, {})
228
229 @patch('softwarecenter.ui.gtk3.panes.availablepane.UnityLauncher'
230 '.send_application_to_launcher')
231 def test_unity_launcher_integration_installation_failure(self,
232 mock_send_application_to_launcher):
233 # test the automatic add to launcher enabled functionality when
234 # a failure is detected during the transaction (aptd emits a
235 # "transaction-stopped" signal for this case)
236 self.config.add_to_unity_launcher = True
237 test_pkgname = "software-center"
238 self.expected_pkgname = test_pkgname
239 self.expected_launcher_info = UnityLauncherInfo("software-center",
240 "softwarecenter",
241 0, 0, 0, 0, # these values are set in availablepane
242 "/usr/share/applications/ubuntu-software-center.desktop",
243 "")
244 app = Application("", test_pkgname)
245 self.available_pane.app_view.emit("application-activated",
246 app)
247 do_events()
248 # aptd will emit a "transaction-stopped" signal if a transaction
249 # error is encountered
250 self._simulate_install_events(app,
251 result_event="transaction-stopped")
252 # ensure that we do not send the application to the launcher
253 # on a failed installation
254 self.assertFalse(mock_send_application_to_launcher.called)
255 # insure that the unity launcher transaction queue is cleared
256 self.assertEqual(
257 self.available_pane.unity_launcher_transaction_queue, {})
258
191259
192class DesktopFilepathConversionTestCase(unittest.TestCase):260class DesktopFilepathConversionTestCase(unittest.TestCase):
193 261

Subscribers

People subscribed via source and target branches