virtual-device: Add support for sleeping and sending errors on list and delete

This commit is contained in:
Marco Trevisan (Treviño) 2021-01-26 01:33:55 +01:00
parent 7ffcc2f9e7
commit 88a38c38af
4 changed files with 95 additions and 10 deletions

View file

@ -83,6 +83,7 @@ struct _FpDeviceVirtualDevice
gboolean match_reported;
gboolean supports_cancellation;
gboolean injected_synthetic_cmd;
gboolean ignore_wait;
};
/* Not really final here, but we can do this to share the FpDeviceVirtualDevice

View file

@ -122,10 +122,19 @@ static void
dev_list (FpDevice *dev)
{
g_autoptr(GPtrArray) prints_list = NULL;
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev);
struct ListData data;
process_cmds (vdev, FALSE, NULL);
process_cmds (vdev, FALSE, &error);
if (should_wait_for_command (vdev, error))
return;
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
fpi_device_list_complete (dev, NULL, g_steal_pointer (&error));
return;
}
prints_list = g_ptr_array_new_full (g_hash_table_size (vdev->prints_storage), NULL);
data.dev = dev;
@ -140,11 +149,20 @@ static void
dev_delete (FpDevice *dev)
{
g_autoptr(GVariant) data = NULL;
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev);
FpPrint *print = NULL;
const char *id = NULL;
process_cmds (vdev, FALSE, NULL);
process_cmds (vdev, FALSE, &error);
if (should_wait_for_command (vdev, error))
return;
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
fpi_device_delete_complete (dev, g_steal_pointer (&error));
return;
}
fpi_device_get_delete_data (dev, &print);

View file

@ -70,6 +70,14 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self)
FP_DEVICE_GET_CLASS (self)->identify (dev);
break;
case FPI_DEVICE_ACTION_LIST:
FP_DEVICE_GET_CLASS (self)->list (dev);
break;
case FPI_DEVICE_ACTION_DELETE:
FP_DEVICE_GET_CLASS (self)->delete (dev);
break;
default:
break;
}
@ -141,6 +149,14 @@ process_cmds (FpDeviceVirtualDevice * self,
return NULL;
}
else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX))
{
g_propagate_error (error,
fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10)));
g_ptr_array_remove_index (self->pending_commands, 0);
return NULL;
}
/* If we are not scanning, then we have to stop here. */
if (!scan)
@ -153,14 +169,6 @@ process_cmds (FpDeviceVirtualDevice * self,
g_ptr_array_remove_index (self->pending_commands, 0);
return res;
}
else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX))
{
g_propagate_error (error,
fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10)));
g_ptr_array_remove_index (self->pending_commands, 0);
return NULL;
}
else if (g_str_has_prefix (cmd, RETRY_CMD_PREFIX))
{
g_propagate_error (error,
@ -338,6 +346,20 @@ wait_for_command_timeout (gpointer data)
GError *error = NULL;
self->wait_command_id = 0;
switch (fpi_device_get_current_action (FP_DEVICE (self)))
{
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_DELETE:
self->ignore_wait = TRUE;
maybe_continue_current_action (self);
self->ignore_wait = FALSE;
return FALSE;
default:
break;
}
error = g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands arrived in time to run!");
fpi_device_action_error (FP_DEVICE (self), error);
@ -351,6 +373,9 @@ should_wait_for_command (FpDeviceVirtualDevice *self,
if (!error && self->sleep_timeout_id)
return TRUE;
if (self->ignore_wait)
return FALSE;
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
return FALSE;

View file

@ -586,6 +586,47 @@ class VirtualDeviceStorage(VirtualDevice):
self.dev.delete_print_sync(p)
self.assertFalse(self.dev.list_prints_sync())
def test_delete_error(self):
deleted_res = None
def on_deleted(dev, res):
nonlocal deleted_res
try:
deleted_res = dev.delete_print_finish(res)
except GLib.Error as e:
deleted_res = e
self.send_command('SLEEP', 100)
self.send_error(FPrint.DeviceError.DATA_NOT_FOUND)
self.dev.delete_print(FPrint.Print.new(self.dev), callback=on_deleted)
self.wait_timeout(2)
self.assertIsNone(deleted_res)
while not deleted_res:
ctx.iteration(True)
self.assertEqual(deleted_res.code, int(FPrint.DeviceError.DATA_NOT_FOUND))
def test_list_error(self):
list_res = None
def on_listed(dev, res):
nonlocal list_res
try:
list_res = dev.list_prints_finish(res)
except GLib.Error as e:
list_res = e
self.send_command('SLEEP', 100)
self.send_error(FPrint.DeviceError.BUSY)
self.dev.list_prints(callback=on_listed)
self.wait_timeout(2)
self.assertIsNone(list_res)
while not list_res:
ctx.iteration(True)
self.assertEqual(list_res.code, int(FPrint.DeviceError.BUSY))
def test_list_delete_missing(self):
p = self.enroll_print('testprint', FPrint.Finger.RIGHT_THUMB)
self.send_command('REMOVE', 'testprint')