diff --git a/src/device.c b/src/device.c index 83e88c5..b554b1f 100644 --- a/src/device.c +++ b/src/device.c @@ -1163,21 +1163,23 @@ can_stop_action (FprintDevice *rdev, GError **error) { FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev); + gboolean action_matches; switch (priv->current_action) { case ACTION_IDENTIFY: case ACTION_VERIFY: - if (action == ACTION_IDENTIFY || action == ACTION_VERIFY) - return TRUE; + action_matches = (action == ACTION_VERIFY || action == ACTION_IDENTIFY); break; default: - if (priv->current_action == action) - return TRUE; + action_matches = priv->current_action == action; } - if (priv->current_action != ACTION_NONE) + if (action_matches && !priv->current_cancel_invocation) + return TRUE; + + if (priv->current_action != ACTION_NONE || action_matches) { g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE, "Another operation is already in progress"); diff --git a/tests/fprintd.py b/tests/fprintd.py index 530ac0f..7ac45f8 100755 --- a/tests/fprintd.py +++ b/tests/fprintd.py @@ -396,17 +396,18 @@ class FPrintdTest(dbusmock.DBusTestCase): def _method_call_handler(self, proxy, res): try: - self._async_call_res = proxy.call_finish(res) + self._async_call_res.append(proxy.call_finish(res)) except Exception as e: - self._async_call_res = e + self._async_call_res.append(e) - def wait_for_device_reply(self): - self._async_call_res = None - while not self._async_call_res: + def wait_for_device_reply(self, expected_replies=1): + self._async_call_res = [] + while len(self._async_call_res) != expected_replies: ctx.iteration(True) - if isinstance(self._async_call_res, Exception): - raise self._async_call_res + for res in self._async_call_res: + if isinstance(res, Exception): + raise res def gdbus_device_method_call_process(self, method, args=[]): return subprocess.Popen([ @@ -1677,9 +1678,11 @@ class FPrintdVirtualDeviceEnrollTests(FPrintdVirtualDeviceBaseTest): self._abort = False self.device.Claim('(s)', 'testuser') self.device.EnrollStart('(s)', 'left-middle-finger') + self.stop_on_teardown = True def tearDown(self): - self.device.EnrollStop() + if self.stop_on_teardown: + self.device.EnrollStop() self.device.Release() super().tearDown() @@ -1762,6 +1765,16 @@ class FPrintdVirtualDeviceEnrollTests(FPrintdVirtualDeviceBaseTest): with self.assertFprintError('AlreadyInUse'): self.device.DeleteEnrolledFinger('(s)', 'left-thumb') + def test_enroll_concourrent_stop(self): + self.stop_on_teardown = False + self.call_device_method_async('EnrollStop', '()', []) + self.call_device_method_async('EnrollStop', '()', []) + + with self.assertFprintError('AlreadyInUse'): + self.wait_for_device_reply(expected_replies=2) + + self.assertIn(GLib.Variant('()', ()), self._async_call_res) + class FPrintdVirtualDeviceVerificationTests(FPrintdVirtualDeviceBaseTest): @@ -1770,6 +1783,7 @@ class FPrintdVirtualDeviceVerificationTests(FPrintdVirtualDeviceBaseTest): super().setUpClass() cls.enroll_finger = 'left-middle-finger' cls.verify_finger = cls.enroll_finger + cls.stop_on_teardown = True def setUp(self): super().setUp() @@ -1778,7 +1792,8 @@ class FPrintdVirtualDeviceVerificationTests(FPrintdVirtualDeviceBaseTest): self.device.VerifyStart('(s)', self.verify_finger) def tearDown(self): - self.device.VerifyStop() + if self.stop_on_teardown: + self.device.VerifyStop() self.device.Release() super().tearDown() @@ -1899,6 +1914,16 @@ class FPrintdVirtualDeviceVerificationTests(FPrintdVirtualDeviceBaseTest): with self.assertFprintError('AlreadyInUse'): self.device.DeleteEnrolledFinger('(s)', 'left-thumb') + def test_verify_concourrent_stop(self): + self.stop_on_teardown = False + self.call_device_method_async('VerifyStop', '()', []) + self.call_device_method_async('VerifyStop', '()', []) + + with self.assertFprintError('AlreadyInUse'): + self.wait_for_device_reply(expected_replies=2) + + self.assertIn(GLib.Variant('()', ()), self._async_call_res) + class FPrintdVirtualDeviceIdentificationTests(FPrintdVirtualDeviceVerificationTests): '''This class will just repeat the tests of FPrintdVirtualDeviceVerificationTests