From ef805f2341dd8559ec93f65132fd744b213faead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 9 Apr 2021 21:31:43 +0200 Subject: [PATCH] device: Expose supported features publicly as FpDeviceFeature It can be convenient for device users to check what it supports, without having multiple functions to check each single feature. So expose this and add tests. --- doc/libfprint-2-sections.txt | 4 +- libfprint/drivers/goodixmoc/goodix.c | 2 +- libfprint/drivers/virtual-device-storage.c | 2 +- libfprint/fp-device.c | 52 +++- libfprint/fp-device.h | 28 +++ libfprint/fpi-device.c | 14 +- libfprint/fpi-device.h | 26 +- tests/capture.py | 8 + tests/goodixmoc/custom.py | 8 + tests/synaptics/custom.py | 8 + tests/test-fp-device.c | 3 + tests/test-fpi-device.c | 270 ++++++++++++++------- tests/virtual-device.py | 20 ++ tests/virtual-image.py | 14 ++ 14 files changed, 330 insertions(+), 129 deletions(-) diff --git a/doc/libfprint-2-sections.txt b/doc/libfprint-2-sections.txt index 998ea2e1..3d676862 100644 --- a/doc/libfprint-2-sections.txt +++ b/doc/libfprint-2-sections.txt @@ -20,6 +20,7 @@ FP_TYPE_DEVICE FP_DEVICE_RETRY FP_DEVICE_ERROR FpDeviceType +FpDeviceFeature FpScanType FpDeviceRetry FpDeviceError @@ -33,6 +34,8 @@ fp_device_get_name fp_device_get_scan_type fp_device_get_nr_enroll_stages fp_device_get_finger_status +fp_device_get_features +fp_device_has_feature fp_device_has_storage fp_device_supports_identify fp_device_supports_capture @@ -131,7 +134,6 @@ fpi_get_driver_types FpDeviceClass FpTimeoutFunc FpiDeviceAction -FpiDeviceFeature FpIdEntry FpiDeviceUdevSubtypeFlags fpi_device_get_usb_device diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index b57ee3c1..3f296422 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -1581,5 +1581,5 @@ fpi_device_goodixmoc_class_init (FpiDeviceGoodixMocClass *klass) dev_class->identify = gx_fp_verify_identify; fpi_device_class_auto_initialize_features (dev_class); - dev_class->features |= FPI_DEVICE_FEATURE_DUPLICATES_CHECK; + dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK; } diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index 9591dccb..cc67d8c5 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -246,5 +246,5 @@ fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass dev_class->delete = dev_delete; fpi_device_class_auto_initialize_features (dev_class); - dev_class->features |= FPI_DEVICE_FEATURE_DUPLICATES_CHECK; + dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK; } diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c index c2101a64..5027e033 100644 --- a/libfprint/fp-device.c +++ b/libfprint/fp-device.c @@ -140,7 +140,7 @@ fp_device_constructed (GObject *object) FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self); FpDevicePrivate *priv = fp_device_get_instance_private (self); - g_assert (cls->features != FPI_DEVICE_FEATURE_NONE); + g_assert (cls->features != FP_DEVICE_FEATURE_NONE); priv->type = cls->type; if (cls->nr_enroll_stages) @@ -629,7 +629,7 @@ fp_device_supports_identify (FpDevice *device) g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); - return cls->identify && !!(cls->features & FPI_DEVICE_FEATURE_IDENTIFY); + return cls->identify && !!(cls->features & FP_DEVICE_FEATURE_IDENTIFY); } /** @@ -647,7 +647,7 @@ fp_device_supports_capture (FpDevice *device) g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); - return cls->capture && !!(cls->features & FPI_DEVICE_FEATURE_CAPTURE); + return cls->capture && !!(cls->features & FP_DEVICE_FEATURE_CAPTURE); } /** @@ -666,7 +666,7 @@ fp_device_has_storage (FpDevice *device) g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); - return !!(cls->features & FPI_DEVICE_FEATURE_STORAGE); + return !!(cls->features & FP_DEVICE_FEATURE_STORAGE); } /** @@ -976,7 +976,7 @@ fp_device_verify (FpDevice *device, return; } - if (!cls->verify || !(cls->features & FPI_DEVICE_FEATURE_VERIFY)) + if (!cls->verify || !(cls->features & FP_DEVICE_FEATURE_VERIFY)) { g_task_return_error (task, fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED, @@ -1211,7 +1211,7 @@ fp_device_capture (FpDevice *device, return; } - if (!cls->capture || !(cls->features & FPI_DEVICE_FEATURE_CAPTURE)) + if (!cls->capture || !(cls->features & FP_DEVICE_FEATURE_CAPTURE)) { g_task_return_error (task, fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED, @@ -1295,7 +1295,7 @@ fp_device_delete_print (FpDevice *device, } /* Succeed immediately if delete is not implemented. */ - if (!cls->delete || !(cls->features & FPI_DEVICE_FEATURE_STORAGE_DELETE)) + if (!cls->delete || !(cls->features & FP_DEVICE_FEATURE_STORAGE_DELETE)) { g_task_return_boolean (task, TRUE); return; @@ -1672,3 +1672,41 @@ fp_device_list_prints_sync (FpDevice *device, return fp_device_list_prints_finish (device, task, error); } + +/** + * fp_device_get_features: + * @device: a #FpDevice + * + * Gets the #FpDeviceFeature's supported by the @device. + * + * Returns: #FpDeviceFeature flags of supported features + */ +FpDeviceFeature +fp_device_get_features (FpDevice *device) +{ + g_return_val_if_fail (FP_IS_DEVICE (device), FP_DEVICE_FEATURE_NONE); + + return FP_DEVICE_GET_CLASS (device)->features; +} + +/** + * fp_device_has_feature: + * @device: a #FpDevice + * @feature: #FpDeviceFeature flags to check against device supported features + * + * Checks if @device supports the requested #FpDeviceFeature's. + * See fp_device_get_features() + * + * Returns: %TRUE if supported, %FALSE otherwise + */ +gboolean +fp_device_has_feature (FpDevice *device, + FpDeviceFeature feature) +{ + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + if (feature == FP_DEVICE_FEATURE_NONE) + return fp_device_get_features (device) == feature; + + return (fp_device_get_features (device) & feature) == feature; +} diff --git a/libfprint/fp-device.h b/libfprint/fp-device.h index 806ad195..2b358945 100644 --- a/libfprint/fp-device.h +++ b/libfprint/fp-device.h @@ -47,6 +47,30 @@ typedef enum { FP_DEVICE_TYPE_USB, } FpDeviceType; +/** + * FpDeviceFeature: + * @FP_DEVICE_FEATURE_NONE: Device does not support any feature + * @FP_DEVICE_FEATURE_CAPTURE: Supports image capture + * @FP_DEVICE_FEATURE_VERIFY: Supports finger verification + * @FP_DEVICE_FEATURE_IDENTIFY: Supports finger identification + * @FP_DEVICE_FEATURE_STORAGE: Device has a persistent storage + * @FP_DEVICE_FEATURE_STORAGE_LIST: Supports listing the storage templates + * @FP_DEVICE_FEATURE_STORAGE_DELETE: Supports deleting stored templates + * @FP_DEVICE_FEATURE_STORAGE_CLEAR: Supports clearing the whole storage + * @FP_DEVICE_FEATURE_DUPLICATES_CHECK: Natively supports duplicates detection + */ +typedef enum /*< flags >*/ { + FP_DEVICE_FEATURE_NONE = 0, + FP_DEVICE_FEATURE_CAPTURE = 1 << 0, + FP_DEVICE_FEATURE_IDENTIFY = 1 << 1, + FP_DEVICE_FEATURE_VERIFY = 1 << 2, + FP_DEVICE_FEATURE_STORAGE = 1 << 3, + FP_DEVICE_FEATURE_STORAGE_LIST = 1 << 4, + FP_DEVICE_FEATURE_STORAGE_DELETE = 1 << 5, + FP_DEVICE_FEATURE_STORAGE_CLEAR = 1 << 6, + FP_DEVICE_FEATURE_DUPLICATES_CHECK = 1 << 7, +} FpDeviceFeature; + /** * FpScanType: * @FP_SCAN_TYPE_SWIPE: Sensor requires swiping the finger. @@ -178,6 +202,10 @@ FpScanType fp_device_get_scan_type (FpDevice *device); FpFingerStatusFlags fp_device_get_finger_status (FpDevice *device); gint fp_device_get_nr_enroll_stages (FpDevice *device); +FpDeviceFeature fp_device_get_features (FpDevice *device); +gboolean fp_device_has_feature (FpDevice *device, + FpDeviceFeature feature); + gboolean fp_device_supports_identify (FpDevice *device); gboolean fp_device_supports_capture (FpDevice *device); gboolean fp_device_has_storage (FpDevice *device); diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c index f6da050b..2cd06371 100644 --- a/libfprint/fpi-device.c +++ b/libfprint/fpi-device.c @@ -59,24 +59,24 @@ fpi_device_class_auto_initialize_features (FpDeviceClass *device_class) g_return_if_fail (FP_IS_DEVICE_CLASS (device_class)); if (device_class->capture) - device_class->features |= FPI_DEVICE_FEATURE_CAPTURE; + device_class->features |= FP_DEVICE_FEATURE_CAPTURE; if (device_class->verify) - device_class->features |= FPI_DEVICE_FEATURE_VERIFY; + device_class->features |= FP_DEVICE_FEATURE_VERIFY; if (device_class->identify) - device_class->features |= FPI_DEVICE_FEATURE_IDENTIFY; + device_class->features |= FP_DEVICE_FEATURE_IDENTIFY; if (device_class->list) { - device_class->features |= FPI_DEVICE_FEATURE_STORAGE; - device_class->features |= FPI_DEVICE_FEATURE_STORAGE_LIST; + device_class->features |= FP_DEVICE_FEATURE_STORAGE; + device_class->features |= FP_DEVICE_FEATURE_STORAGE_LIST; } if (device_class->delete) { - device_class->features |= FPI_DEVICE_FEATURE_STORAGE; - device_class->features |= FPI_DEVICE_FEATURE_STORAGE_DELETE; + device_class->features |= FP_DEVICE_FEATURE_STORAGE; + device_class->features |= FP_DEVICE_FEATURE_STORAGE_DELETE; } } diff --git a/libfprint/fpi-device.h b/libfprint/fpi-device.h index 38a4574f..f669d293 100644 --- a/libfprint/fpi-device.h +++ b/libfprint/fpi-device.h @@ -69,30 +69,6 @@ struct _FpIdEntry guint64 driver_data; }; -/** - * FpiDeviceFeature: - * @FPI_DEVICE_FEATURE_NONE: Device does not support any feature - * @FPI_DEVICE_FEATURE_CAPTURE: Supports image capture - * @FPI_DEVICE_FEATURE_IDENTIFY: Supports finger identification - * @FPI_DEVICE_FEATURE_VERIFY: Supports finger verification - * @FPI_DEVICE_FEATURE_STORAGE: Device has a persistent storage - * @FPI_DEVICE_FEATURE_STORAGE_LIST: Supports listing the storage templates - * @FPI_DEVICE_FEATURE_STORAGE_DELETE: Supports deleting stored templates - * @FPI_DEVICE_FEATURE_STORAGE_CLEAR: Supports clearing the whole storage - * @FPI_DEVICE_FEATURE_DUPLICATES_CHECK: Natively supports duplicates detection - */ -typedef enum /*< flags >*/ { - FPI_DEVICE_FEATURE_NONE = 0, - FPI_DEVICE_FEATURE_CAPTURE = 1 << 0, - FPI_DEVICE_FEATURE_IDENTIFY = 1 << 1, - FPI_DEVICE_FEATURE_VERIFY = 1 << 2, - FPI_DEVICE_FEATURE_STORAGE = 1 << 3, - FPI_DEVICE_FEATURE_STORAGE_LIST = 1 << 4, - FPI_DEVICE_FEATURE_STORAGE_DELETE = 1 << 5, - FPI_DEVICE_FEATURE_STORAGE_CLEAR = 1 << 6, - FPI_DEVICE_FEATURE_DUPLICATES_CHECK = 1 << 7, -} FpiDeviceFeature; - /** * FpDeviceClass: * @id: ID string for the driver. Should be a valid C identifier and should @@ -159,7 +135,7 @@ struct _FpDeviceClass const gchar *full_name; FpDeviceType type; const FpIdEntry *id_table; - FpiDeviceFeature features; + FpDeviceFeature features; /* Defaults for device properties */ gint nr_enroll_stages; diff --git a/tests/capture.py b/tests/capture.py index 88ed81fb..c25afbf4 100755 --- a/tests/capture.py +++ b/tests/capture.py @@ -17,6 +17,14 @@ c.enumerate() devices = c.get_devices() d = devices[0] +assert d.has_feature(FPrint.DeviceFeature.CAPTURE) +assert d.has_feature(FPrint.DeviceFeature.IDENTIFY) +assert d.has_feature(FPrint.DeviceFeature.VERIFY) +assert not d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK) +assert not d.has_feature(FPrint.DeviceFeature.STORAGE) +assert not d.has_feature(FPrint.DeviceFeature.STORAGE_LIST) +assert not d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE) +assert not d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR) del devices d.open_sync() diff --git a/tests/goodixmoc/custom.py b/tests/goodixmoc/custom.py index 17f35622..2fe6edd9 100755 --- a/tests/goodixmoc/custom.py +++ b/tests/goodixmoc/custom.py @@ -14,6 +14,14 @@ d = devices[0] del devices assert d.get_driver() == "goodixmoc" +assert not d.has_feature(FPrint.DeviceFeature.CAPTURE) +assert d.has_feature(FPrint.DeviceFeature.IDENTIFY) +assert d.has_feature(FPrint.DeviceFeature.VERIFY) +assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK) +assert d.has_feature(FPrint.DeviceFeature.STORAGE) +assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST) +assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE) +assert not d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR) d.open_sync() diff --git a/tests/synaptics/custom.py b/tests/synaptics/custom.py index a1d03521..325f53de 100755 --- a/tests/synaptics/custom.py +++ b/tests/synaptics/custom.py @@ -14,6 +14,14 @@ d = devices[0] del devices assert d.get_driver() == "synaptics" +assert not d.has_feature(FPrint.DeviceFeature.CAPTURE) +assert d.has_feature(FPrint.DeviceFeature.IDENTIFY) +assert d.has_feature(FPrint.DeviceFeature.VERIFY) +assert not d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK) +assert d.has_feature(FPrint.DeviceFeature.STORAGE) +assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST) +assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE) +assert not d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR) d.open_sync() diff --git a/tests/test-fp-device.c b/tests/test-fp-device.c index b8f6f172..a4730928 100644 --- a/tests/test-fp-device.c +++ b/tests/test-fp-device.c @@ -202,6 +202,7 @@ test_device_supports_identify (void) g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_true (fp_device_has_feature (tctx->device, FP_DEVICE_FEATURE_IDENTIFY)); g_assert_true (fp_device_supports_identify (tctx->device)); } @@ -211,6 +212,7 @@ test_device_supports_capture (void) g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_true (fp_device_has_feature (tctx->device, FP_DEVICE_FEATURE_CAPTURE)); g_assert_true (fp_device_supports_capture (tctx->device)); } @@ -220,6 +222,7 @@ test_device_has_storage (void) g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_false (fp_device_has_feature (tctx->device, FP_DEVICE_FEATURE_STORAGE)); g_assert_false (fp_device_has_storage (tctx->device)); } diff --git a/tests/test-fpi-device.c b/tests/test-fpi-device.c index 7f2b21f1..5a5ee963 100644 --- a/tests/test-fpi-device.c +++ b/tests/test-fpi-device.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "fp-device.h" +#include "fp-enums.h" #include #define FP_COMPONENT "device" @@ -506,21 +508,103 @@ test_driver_get_driver_data (void) g_assert_cmpuint (fpi_device_get_driver_data (device), ==, driver_data); } +static void +driver_feature_changes_check (FpDevice *device, gboolean add) +{ + g_autoptr(GFlagsClass) features_class = g_type_class_ref (FP_TYPE_DEVICE_FEATURE); + FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device); + guint expected_features; + guint initial_value; + guint i; + + if (add) + initial_value = FP_DEVICE_FEATURE_NONE; + else + initial_value = features_class->mask; + + g_assert_cmpuint (fp_device_get_features (device), ==, initial_value); + + for (i = 0, expected_features = initial_value; i < features_class->n_values; ++i) + { + FpDeviceFeature feature = features_class->values[i].value; + FpDeviceFeature added_feature = add ? feature : FP_DEVICE_FEATURE_NONE; + FpDeviceFeature removed_feature = add ? FP_DEVICE_FEATURE_NONE : feature; + + dev_class->features |= added_feature; + dev_class->features &= ~removed_feature; + + expected_features |= added_feature; + expected_features &= ~removed_feature; + + g_assert_cmpuint (fp_device_get_features (device), ==, expected_features); + + if (added_feature != FP_DEVICE_FEATURE_NONE) + g_assert_true (fp_device_has_feature (device, added_feature)); + else if (dev_class->features != FP_DEVICE_FEATURE_NONE) + g_assert_false (fp_device_has_feature (device, added_feature)); + else + g_assert_true (fp_device_has_feature (device, added_feature)); + + if (removed_feature != FP_DEVICE_FEATURE_NONE) + g_assert_false (fp_device_has_feature (device, removed_feature)); + else if (dev_class->features != FP_DEVICE_FEATURE_NONE) + g_assert_false (fp_device_has_feature (device, removed_feature)); + else + g_assert_true (fp_device_has_feature (device, removed_feature)); + + g_assert_true (fp_device_has_feature (device, expected_features)); + } + + if (add) + g_assert_cmpuint (fp_device_get_features (device), ==, features_class->mask); + else + g_assert_cmpuint (fp_device_get_features (device), ==, FP_DEVICE_FEATURE_NONE); +} + +static void +test_driver_features (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + + dev_class->features = FP_DEVICE_FEATURE_NONE; + driver_feature_changes_check (device, TRUE); + driver_feature_changes_check (device, FALSE); +} + static void test_driver_initial_features (void) { g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device); - g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); + + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_CAPTURE)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_VERIFY)); + g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_DUPLICATES_CHECK)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_LIST)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_DELETE)); + g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_CLEAR)); + + g_assert_cmpuint (fp_device_get_features (device), + ==, + FP_DEVICE_FEATURE_CAPTURE | + FP_DEVICE_FEATURE_IDENTIFY | + FP_DEVICE_FEATURE_VERIFY | + FP_DEVICE_FEATURE_STORAGE | + FP_DEVICE_FEATURE_STORAGE_LIST | + FP_DEVICE_FEATURE_STORAGE_DELETE); } static void @@ -533,19 +617,19 @@ test_driver_initial_features_none (void) dev_class->verify = NULL; dev_class->identify = NULL; dev_class->delete = NULL; - dev_class->features = FPI_DEVICE_FEATURE_NONE; + dev_class->features = FP_DEVICE_FEATURE_NONE; fpi_device_class_auto_initialize_features (dev_class); - g_assert_cmpuint (dev_class->features, ==, FPI_DEVICE_FEATURE_NONE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_cmpuint (dev_class->features, ==, FP_DEVICE_FEATURE_NONE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_CAPTURE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -554,19 +638,19 @@ test_driver_initial_features_no_capture (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); dev_class->capture = NULL; - dev_class->features = FPI_DEVICE_FEATURE_NONE; + dev_class->features = FP_DEVICE_FEATURE_NONE; fpi_device_class_auto_initialize_features (dev_class); - g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -575,19 +659,19 @@ test_driver_initial_features_no_verify (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); dev_class->verify = NULL; - dev_class->features = FPI_DEVICE_FEATURE_NONE; + dev_class->features = FP_DEVICE_FEATURE_NONE; fpi_device_class_auto_initialize_features (dev_class); - g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -596,19 +680,19 @@ test_driver_initial_features_no_identify (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); dev_class->identify = NULL; - dev_class->features = FPI_DEVICE_FEATURE_NONE; + dev_class->features = FP_DEVICE_FEATURE_NONE; fpi_device_class_auto_initialize_features (dev_class); - g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -618,19 +702,19 @@ test_driver_initial_features_no_storage (void) dev_class->list = NULL; dev_class->delete = NULL; - dev_class->features = FPI_DEVICE_FEATURE_NONE; + dev_class->features = FP_DEVICE_FEATURE_NONE; fpi_device_class_auto_initialize_features (dev_class); - g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -639,19 +723,19 @@ test_driver_initial_features_no_list (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); dev_class->list = NULL; - dev_class->features = FPI_DEVICE_FEATURE_NONE; + dev_class->features = FP_DEVICE_FEATURE_NONE; fpi_device_class_auto_initialize_features (dev_class); - g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -660,19 +744,19 @@ test_driver_initial_features_no_delete (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); dev_class->list = NULL; - dev_class->features = FPI_DEVICE_FEATURE_NONE; + dev_class->features = FP_DEVICE_FEATURE_NONE; fpi_device_class_auto_initialize_features (dev_class); - g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); - g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -1173,7 +1257,7 @@ test_driver_verify_not_supported (void) FpiDeviceFake *fake_dev; gboolean match; - dev_class->features &= ~FPI_DEVICE_FEATURE_VERIFY; + dev_class->features &= ~FP_DEVICE_FEATURE_VERIFY; device = auto_close_fake_device_new (); fake_dev = FPI_DEVICE_FAKE (device); @@ -1505,6 +1589,7 @@ test_driver_supports_identify (void) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); g_assert_true (fp_device_supports_identify (device)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY)); } static void @@ -1513,10 +1598,11 @@ test_driver_do_not_support_identify (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); g_autoptr(FpDevice) device = NULL; - dev_class->features &= ~FPI_DEVICE_FEATURE_IDENTIFY; + dev_class->features &= ~FP_DEVICE_FEATURE_IDENTIFY; device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); g_assert_false (fp_device_supports_identify (device)); + g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY)); } static void @@ -1536,6 +1622,7 @@ test_driver_identify (void) fp_print_set_description (expected_matched, "fake-verified"); g_assert_true (fp_device_supports_identify (device)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY)); match_data->gallery = prints; @@ -1569,6 +1656,7 @@ test_driver_identify_fail (void) FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device); g_assert_true (fp_device_supports_identify (device)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY)); fake_dev->ret_print = make_fake_print (device, NULL); g_assert_true (fp_device_identify_sync (device, prints, NULL, @@ -1605,6 +1693,7 @@ test_driver_identify_retry (void) fp_print_set_description (expected_matched, "fake-verified"); g_assert_true (fp_device_supports_identify (device)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY)); fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL); g_assert_false (fp_device_identify_sync (device, prints, NULL, @@ -1639,6 +1728,7 @@ test_driver_identify_error (void) fp_print_set_description (expected_matched, "fake-verified"); g_assert_true (fp_device_supports_identify (device)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY)); fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL); g_assert_false (fp_device_identify_sync (device, prints, NULL, @@ -1841,11 +1931,12 @@ test_driver_supports_capture (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); g_autoptr(FpDevice) device = NULL; - dev_class->features |= FPI_DEVICE_FEATURE_CAPTURE; + dev_class->features |= FP_DEVICE_FEATURE_CAPTURE; dev_class->capture = fake_device_stub_capture; device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); g_assert_true (fp_device_supports_capture (device)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_CAPTURE)); } static void @@ -1854,11 +1945,12 @@ test_driver_do_not_support_capture (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); g_autoptr(FpDevice) device = NULL; - dev_class->features &= ~FPI_DEVICE_FEATURE_CAPTURE; + dev_class->features &= ~FP_DEVICE_FEATURE_CAPTURE; dev_class->capture = NULL; device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); g_assert_false (fp_device_supports_capture (device)); + g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_CAPTURE)); } static void @@ -1890,7 +1982,7 @@ test_driver_capture_not_supported (void) gboolean wait_for_finger = TRUE; FpiDeviceFake *fake_dev; - dev_class->features &= ~FPI_DEVICE_FEATURE_CAPTURE; + dev_class->features &= ~FP_DEVICE_FEATURE_CAPTURE; device = auto_close_fake_device_new (); fake_dev = FPI_DEVICE_FAKE (device); @@ -1928,10 +2020,11 @@ test_driver_has_storage (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); g_autoptr(FpDevice) device = NULL; - dev_class->features |= FPI_DEVICE_FEATURE_STORAGE; + dev_class->features |= FP_DEVICE_FEATURE_STORAGE; device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); g_assert_true (fp_device_has_storage (device)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE)); } static void @@ -1940,10 +2033,11 @@ test_driver_has_not_storage (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); g_autoptr(FpDevice) device = NULL; - dev_class->features &= ~FPI_DEVICE_FEATURE_STORAGE; + dev_class->features &= ~FP_DEVICE_FEATURE_STORAGE; device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); g_assert_false (fp_device_has_storage (device)); + g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE)); } static void @@ -1992,10 +2086,11 @@ test_driver_list_no_storage (void) g_autoptr(GPtrArray) prints = NULL; g_autoptr(GError) error = NULL; - dev_class->features &= ~FPI_DEVICE_FEATURE_STORAGE; + dev_class->features &= ~FP_DEVICE_FEATURE_STORAGE; device = auto_close_fake_device_new (); g_assert_false (fp_device_has_storage (device)); + g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE)); prints = fp_device_list_prints_sync (device, NULL, &error); g_assert_null (prints); @@ -2661,6 +2756,7 @@ main (int argc, char *argv[]) g_test_add_func ("/driver/get_usb_device", test_driver_get_usb_device); g_test_add_func ("/driver/get_virtual_env", test_driver_get_virtual_env); g_test_add_func ("/driver/get_driver_data", test_driver_get_driver_data); + g_test_add_func ("/driver/features", test_driver_features); g_test_add_func ("/driver/initial_features", test_driver_initial_features); g_test_add_func ("/driver/initial_features/none", test_driver_initial_features_none); g_test_add_func ("/driver/initial_features/no_capture", test_driver_initial_features_no_capture); diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 27cafdd0..46fedbaa 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -352,6 +352,16 @@ class VirtualDevice(VirtualDeviceBase): self.assertEqual(self.dev.props.nr_enroll_stages, self.dev.get_nr_enroll_stages()) self.assertEqual(self.dev.props.open, self.dev.is_open()) + def test_device_features(self): + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.CAPTURE)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.IDENTIFY)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.VERIFY)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_LIST)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)) + def test_open_error(self): self._close_on_teardown = False self.send_command('IGNORED_COMMAND') # This will be consumed by close @@ -1019,6 +1029,16 @@ class VirtualDeviceStorage(VirtualDevice): self.assertFalse(self.dev.supports_capture()) self.assertTrue(self.dev.has_storage()) + def test_device_features(self): + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.CAPTURE)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.IDENTIFY)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.VERIFY)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_LIST)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)) + def test_duplicate_enroll(self): self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE) with self.assertRaises(GLib.Error) as error: diff --git a/tests/virtual-image.py b/tests/virtual-image.py index 7609bd65..2ee376d1 100755 --- a/tests/virtual-image.py +++ b/tests/virtual-image.py @@ -140,6 +140,20 @@ class VirtualImage(unittest.TestCase): while iterate and ctx.pending(): ctx.iteration(False) + def test_features(self): + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.CAPTURE)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.IDENTIFY)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.VERIFY)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_LIST)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)) + self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)) + self.assertEqual(self.dev.get_features(), + FPrint.DeviceFeature.CAPTURE | + FPrint.DeviceFeature.IDENTIFY | + FPrint.DeviceFeature.VERIFY) + def test_capture_prevents_close(self): cancel = Gio.Cancellable() def cancelled_cb(dev, res, obj):