virtual-device: Add support for sleep command

It can be used to delay operations, simulating a busy device.
This commit is contained in:
Marco Trevisan (Treviño) 2021-01-25 16:41:55 +01:00
parent 89b4c4ee75
commit 18db20d160
3 changed files with 53 additions and 3 deletions

View file

@ -78,6 +78,7 @@ struct _FpDeviceVirtualDevice
GHashTable *prints_storage; GHashTable *prints_storage;
guint wait_command_id; guint wait_command_id;
guint sleep_timeout_id;
guint enroll_stages_passed; guint enroll_stages_passed;
}; };

View file

@ -40,6 +40,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE)
#define ERROR_CMD_PREFIX "ERROR " #define ERROR_CMD_PREFIX "ERROR "
#define RETRY_CMD_PREFIX "RETRY " #define RETRY_CMD_PREFIX "RETRY "
#define FINGER_CMD_PREFIX "FINGER " #define FINGER_CMD_PREFIX "FINGER "
#define SLEEP_CMD_PREFIX "SLEEP "
#define SET_ENROLL_STAGES_PREFIX "SET_ENROLL_STAGES " #define SET_ENROLL_STAGES_PREFIX "SET_ENROLL_STAGES "
#define SET_SCAN_TYPE_PREFIX "SET_SCAN_TYPE " #define SET_SCAN_TYPE_PREFIX "SET_SCAN_TYPE "
@ -70,6 +71,22 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self)
} }
} }
static gboolean
sleep_timeout_cb (gpointer data)
{
FpDeviceVirtualDevice *self = data;
self->sleep_timeout_id = 0;
if (g_cancellable_is_cancelled (self->cancellable))
return FALSE;
g_debug ("Sleeping completed");
maybe_continue_current_action (self);
return FALSE;
}
char * char *
process_cmds (FpDeviceVirtualDevice * self, process_cmds (FpDeviceVirtualDevice * self,
gboolean scan, gboolean scan,
@ -101,6 +118,16 @@ process_cmds (FpDeviceVirtualDevice * self,
g_ptr_array_remove_index (self->pending_commands, 0); g_ptr_array_remove_index (self->pending_commands, 0);
continue; continue;
} }
else if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX))
{
guint64 sleep_ms = g_ascii_strtoull (cmd + strlen (SLEEP_CMD_PREFIX), NULL, 10);
g_debug ("Sleeping %lums", sleep_ms);
self->sleep_timeout_id = g_timeout_add (sleep_ms, sleep_timeout_cb, self);
g_ptr_array_remove_index (self->pending_commands, 0);
return NULL;
}
/* If we are not scanning, then we have to stop here. */ /* If we are not scanning, then we have to stop here. */
if (!scan) if (!scan)
@ -300,6 +327,9 @@ gboolean
should_wait_for_command (FpDeviceVirtualDevice *self, should_wait_for_command (FpDeviceVirtualDevice *self,
GError *error) GError *error)
{ {
if (!error && self->sleep_timeout_id)
return TRUE;
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
return FALSE; return FALSE;
@ -433,6 +463,7 @@ dev_deinit (FpDevice *dev)
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
g_clear_handle_id (&self->wait_command_id, g_source_remove); g_clear_handle_id (&self->wait_command_id, g_source_remove);
g_clear_handle_id (&self->sleep_timeout_id, g_source_remove);
g_cancellable_cancel (self->cancellable); g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable); g_clear_object (&self->cancellable);
g_clear_object (&self->listener); g_clear_object (&self->listener);

View file

@ -96,7 +96,7 @@ class VirtualDevice(unittest.TestCase):
def send_command(self, command, *args): def send_command(self, command, *args):
self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY', self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY',
'FINGER', 'UNPLUG', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE']) 'FINGER', 'UNPLUG', 'SLEEP', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE'])
with Connection(self.sockaddr) as con: with Connection(self.sockaddr) as con:
params = ' '.join(str(p) for p in args) params = ' '.join(str(p) for p in args)
@ -439,6 +439,24 @@ class VirtualDevice(unittest.TestCase):
with self.assertRaisesRegex(GLib.GError, 'device has been removed from the system'): with self.assertRaisesRegex(GLib.GError, 'device has been removed from the system'):
self.dev.close_sync() self.dev.close_sync()
def test_device_sleep(self):
enrolled = self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE)
timeout_reached = False
def on_timeout():
nonlocal timeout_reached
timeout_reached = True
self.send_command('SLEEP', 1500)
GLib.timeout_add(300, on_timeout)
self.start_verify(enrolled, identify=self.dev.supports_identify())
while not timeout_reached:
ctx.iteration(False)
self.assertFalse(self._verify_completed)
self.cancel_verify()
class VirtualDeviceStorage(VirtualDevice): class VirtualDeviceStorage(VirtualDevice):
def tearDown(self): def tearDown(self):